package com.boyadegroot.divelog.data;

import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Environment;
import android.util.Log;

import com.boyadegroot.divelog.models.Dive;
import com.boyadegroot.divelog.models.DiveBuddy;
import com.boyadegroot.divelog.models.DiveCenter;
import com.boyadegroot.divelog.models.DiveCertification;
import com.boyadegroot.divelog.models.DiveCountry;
import com.boyadegroot.divelog.models.DiveCourse;
import com.boyadegroot.divelog.models.DiveLocation;
import com.boyadegroot.divelog.models.DiveOrganization;
import com.boyadegroot.divelog.models.DiveSample;
import com.boyadegroot.divelog.models.DiveSite;
import com.boyadegroot.divelog.models.DiveTrip;
import com.boyadegroot.divelog.models.Diver;
import com.boyadegroot.divelog.utilities.DateUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.List;

public class DiveLogData {

    private static final String TAG = DiveLogData.class.getName();

    private static DiveLogData sInstance;

    private ContentResolver mResolver;
    private int mDiversCount = 0;

    private DiveLogData(Context context) {
        // Log.v(TAG, "DiveLogDb(Context context)");
        mResolver = context.getContentResolver();
        //DELETEDATABASE(context);
        //SEEDDATABASE(); // seed with all except samples
        //COPYTESTDATABASE(context);
        DELETEDIVERIMAGES(context);
        mDiversCount = getRealDiversCount();
    }

    private void DELETEDIVERIMAGES(Context context) {
        Diver cristian = getDiverByUsername("cristian");
        Diver eva = getDiverByUsername("eva");
        for (File file : context.getDir("diver_images", Context.MODE_PRIVATE).listFiles()) {
            String fileName = file.getName();
            if (fileName.contentEquals(Long.toString(cristian.getId()))) {
                continue;
            } else if (fileName.contentEquals(Long.toString(eva.getId()))) {
                continue;
            } else if (fileName.contentEquals(".nomedia")) {
                continue;
            }
            boolean result = file.delete();
            if (!result) {
                Log.e(TAG, "Could not delete file: " + file.getAbsolutePath());
            }
        }
    }

    private void COPYTESTDATABASE(Context context) {
        try {
            File dbFile = context.getDatabasePath(DiveLogDatabaseContract.DATABASE_NAME);
            File backupFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS), DiveLogDatabaseContract.DATABASE_NAME);
            FileChannel src = new FileInputStream(backupFile).getChannel();
            FileChannel dst = new FileOutputStream(dbFile).getChannel();
            dst.transferFrom(src, 0, src.size());
            src.close();
            dst.close();
        } catch (Exception e) {
            throw new Error(e.getMessage());
        }
    }

    private void SEEDDATABASE() {
        long padi_id = addDiveOrganization("PADI", "Professional Association of Diving Instructors");
        long ssi_id = addDiveOrganization("SSI", "Scuba Schools International");
        long wosd_id = addDiveOrganization("WOSD", "World Organisation of Scuba Diving");
        long fedas_id = addDiveOrganization("FEDAS", "Federación Española De Actividades Subacuáticas");
        long facdas_id = addDiveOrganization("FACDAS", "Federacio Catalana d'Activitats Subaquatiques");
        long nob_id = addDiveOrganization("NOB", "Nederlandse Onderwatersport Bond");
        long scubadiver_id = addDiveCourse("Scuba Diver", padi_id);
        long openwaterdiver_id = addDiveCourse("Open Water Diver", padi_id);
        long advancedopenwaterdiver_id = addDiveCourse("Advanced Open Water Diver", padi_id);
        long enrichedairdiver_id = addDiveCourse("Enriched Air Diver", padi_id);
        long aruba_id = addDiveCountry("Aruba");
        long islamauricio_id = addDiveCountry("Isla Mauricio");
        long espanya_id = addDiveCountry("España");
        long mejico_id = addDiveCountry("Méjico");
        long francia_id = addDiveCountry("Francia");
        long malasia_id = addDiveCountry("Malasia");
        long maldivas_id = addDiveCountry("Maldivas");
        long palau_id = addDiveCountry("Palau");
        long indonesia_id = addDiveCountry("Indonesia");
        long palmbeach_id = addDiveLocation("Palm Beach", aruba_id, 12.56817, -70.0487);
        long petitepointeauxpiments_id = addDiveLocation("Petite Pointe Aux Piments", islamauricio_id, -20.0697, 57.51627);
        long llavaneres_id = addDiveLocation("Llavaneres, Sant Andreu De", espanya_id, 41.55786, 2.5045);
        long playadelcarmen_id = addDiveLocation("Playa Del Carmen", mejico_id, 20.65961, -87.03667);
        long cozumel_id = addDiveLocation("Cozumel", mejico_id, 20.51147, -86.95017);
        long cenotes_id = addDiveLocation("Cenotes", mejico_id, 20.51319, -87.24799);
        long mataro_id = addDiveLocation("Mataró", espanya_id, 41.52921, 2.4449);
        long capdagde_id = addDiveLocation("Cap D'Agde", francia_id, 43.28257, 3.51225);
        long tossademar_id = addDiveLocation("Tossa De Mar", espanya_id, 41.72208, 2.93807);
        long lankayan_id = addDiveLocation("Lankayan", malasia_id, 6.52627, 117.91392);
        long kuredu_id = addDiveLocation("Kuredu", maldivas_id, 5.54572, 73.46566);
        long arenysdemar_id = addDiveLocation("Arenys de Mar", espanya_id, 41.579258, 2.55531);
        long koror_id = addDiveLocation("Koror", palau_id, 7.33412, 134.45712);
        long gili_trawangan_id = addDiveLocation("Gili Trawangan", indonesia_id, -8.34361, 116.04191);
        long aruba_tripid = addDiveTrip("Aruba");
        long islamauricio_tripid = addDiveTrip("Isla Mauricio");
        long playadelcarmen_tripid = addDiveTrip("Playa Del Carmen");
        long capdagde_tripid = addDiveTrip("Cap D'Agde");
        long lankayan_tripid = addDiveTrip("Lankayan");
        long kuredu_tripid = addDiveTrip("Kuredu");
        long palau_tripid = addDiveTrip("Palau");
        long gilitrawangan_tripid = addDiveTrip("Gili Trawangan");
        long pedernales_id = addDiveSite("Pedernales Wreck", palmbeach_id);
        long crater_id = addDiveSite("Crater", petitepointeauxpiments_id);
        long turtlecave_id = addDiveSite("Turtle Cave", petitepointeauxpiments_id);
        long emilyreef_id = addDiveSite("Emily Reef", petitepointeauxpiments_id);
        long lavirgen_id = addDiveSite("La Virgen", llavaneres_id);
        long chunzumbul_id = addDiveSite("Chun-Zumbul", playadelcarmen_id);
        long jardines_id = addDiveSite("Jardines", playadelcarmen_id);
        long santarosa_id = addDiveSite("Santa Rosa", cozumel_id);
        long chankanaab_id = addDiveSite("Chankanaab", cozumel_id);
        long kukulkan_id = addDiveSite("Kukulkan", cenotes_id);
        long chacmool_id = addDiveSite("Chac-Mool", cenotes_id);
        long mamavinya_id = addDiveSite("Mama Viña", playadelcarmen_id);
        long sabalos_id = addDiveSite("Sábalos", playadelcarmen_id);
        long tortugas_id = addDiveSite("Tortugas", playadelcarmen_id);
        long barracuda_id = addDiveSite("Barracuda", playadelcarmen_id);
        long barretadelarbre_id = addDiveSite("Barreta De L'Arbre", mataro_id);
        long larbre_id = addDiveSite("L'Arbre", capdagde_id);
        long marmenuda_id = addDiveSite("Mar Menuda", tossademar_id);
        long jetty_id = addDiveSite("Jetty", lankayan_id);
        long kensrock_id = addDiveSite("Ken's Rock", lankayan_id);
        long southrock_id = addDiveSite("South Rock", lankayan_id);
        long lostworld_id = addDiveSite("Lost World", lankayan_id);
        long billysreef_id = addDiveSite("Billy's Reef", lankayan_id);
        long raycity_id = addDiveSite("Ray City", lankayan_id);
        long sunnuglair_id = addDiveSite("Sunnug Lair", lankayan_id);
        long gobyrock_id = addDiveSite("Goby Rock", lankayan_id);
        long andyant_id = addDiveSite("And & Ant", lankayan_id);
        long lostreef_id = addDiveSite("Lost Reef", lankayan_id);
        long jawfishlair_id = addDiveSite("Jawfish Lair", lankayan_id);
        long melsrock_id = addDiveSite("Mel's Rock", lankayan_id);
        long malumalu_id = addDiveSite("Malu Malu", lankayan_id);
        long ikohsrock_id = addDiveSite("Ikoh's Rock", lankayan_id);
        long fanrock_id = addDiveSite("Fan Rock", lankayan_id);
        long housereef_id = addDiveSite("House Reef", kuredu_id);
        long medadihuraoutreef_id = addDiveSite("Medadi-Hura Outreef", kuredu_id);
        long anumonethila_id = addDiveSite("Anemone Thila", kuredu_id);
        long kureduexpress_id = addDiveSite("Kuredu Express", kuredu_id);
        long madivaruthila_id = addDiveSite("Madivaru Thila", kuredu_id);
        long kureducaves_id = addDiveSite("Kuredu Caves", kuredu_id);
        long kffc_id = addDiveSite("KFFC", kuredu_id);
        long ismaelsthila_id = addDiveSite("Ismael's Thila", kuredu_id);
        long thewall_id = addDiveSite("The Wall", kuredu_id);
        long fushivaruthila_id = addDiveSite("Fushivaru Thila", kuredu_id);
        long nakolhothila_id = addDiveSite("Nakolho Giri", kuredu_id);
        long tingagiri_id = addDiveSite("Tinga Giri", kuredu_id);
        long latheefreef_id = addDiveSite("Latheef Reef", kuredu_id);
        long aaagiri_id = addDiveSite("AAA Giri", kuredu_id);
        long abril_id = addDiveSite("Abril", arenysdemar_id);
        long milanas_id = addDiveSite("Milanas", arenysdemar_id);
        long germanchannel_id = addDiveSite("German Channel", koror_id);
        long blueholes_id = addDiveSite("Blue Holes", koror_id);
        long virginbluehole_id = addDiveSite("Virgin Blue Hole", koror_id);
        long bigdropoff_id = addDiveSite("Big Drop Off", koror_id);
        long jakeseaplane_id = addDiveSite("Jake Seaplane", koror_id);
        long ulongchannel_id = addDiveSite("Ulong Channel", koror_id);
        long ulongwall_id = addDiveSite("Ulong Wall", koror_id);
        long helmetwreck_id = addDiveSite("Helmet Wreck", koror_id);
        long ngerchongoutside_id = addDiveSite("Ngerchong Outside", koror_id);
        long ngerchonginside_id = addDiveSite("Ngerchong Inside", koror_id);
        long chandeliercave_id = addDiveSite("Chandelier Cave", koror_id);
        long bluecorner_id = addDiveSite("Blue Corner", koror_id);
        long ngedbuswall_id = addDiveSite("Ngedbus Wall", koror_id);
        long halikreef_id = addDiveSite("Halik Reef", gili_trawangan_id);
        long menowall_id = addDiveSite("Meno Wall", gili_trawangan_id);
        long sharkpoint_id = addDiveSite("Shark Point", gili_trawangan_id);
        long bountywreck_id = addDiveSite("Bounty Wreck", gili_trawangan_id);
        long secretreef_id = addDiveSite("Secret Reef", gili_trawangan_id);
        long menoslope_id = addDiveSite("Meno Slope", gili_trawangan_id);
        long redsailsports_id = addDiveCenter("Red Sail Sports Aruba", palmbeach_id, "http://www.redsailaruba.com/");
        long easydive_id = addDiveCenter("Easy Dive Mauritius", petitepointeauxpiments_id, "http://www.easydivemauritius.com/");
        long subsiluet_id = addDiveCenter("SubSiluet Llavaneres", llavaneres_id, "http://www.subsiluet.net/");
        long scubalibre_id = addDiveCenter("Scuba Libre Playa Del Carmen", playadelcarmen_id, "http://www.scubalibre.com.mx/");
        long manateediving_id = addDiveCenter("Manatee Diving Mataró", mataro_id, "http://www.pitudiving.net/");
        long abyssplongee_id = addDiveCenter("Abyss Plongée Cap D'Agde", capdagde_id, "http://www.abyssplongee.com/");
        long submares_id = addDiveCenter("SubMares Tossa", tossademar_id, "http://www.submares.com/");
        long lankayanislanddiveresort_id = addDiveCenter("Lankayan Island Dive Resort", lankayan_id, "http://www.lankayan-island.com/diving.html");
        long prodivers_id = addDiveCenter("Prodivers Kuredu", kuredu_id, "http://www.prodivers.com/Kuredu-Komandoo-Dive-Sites.aspx");
        long piratasdivers_id = addDiveCenter("Piratas Divers Arenys", arenysdemar_id, "http://www.piratasdivers.com/");
        long fishnfins_id = addDiveCenter("Fish 'n Fins", koror_id, "http://www.fishnfins.com/");
        long ganggadivers_id = addDiveCenter("Gangga Divers", gili_trawangan_id, "http://www.almarik-lombok.com/es/el-buceo");
        long cristian_id = addDiver("cristian", "Cristian", "Boya de Groot", DateUtils.getTimestamp(1974, 2, 5), null);
        long eva_id = addDiver("eva", "Eva", "González González", DateUtils.getTimestamp(1975, 5, 20), null);
        addDiveCertification(cristian_id, DateUtils.getTimestamp(2008, 9, 7), scubadiver_id, redsailsports_id, "0809012499");
        addDiveCertification(cristian_id, DateUtils.getTimestamp(2009, 10, 11), openwaterdiver_id, subsiluet_id, "0910EA7731");
        long cristian_certification_id = addDiveCertification(cristian_id, DateUtils.getTimestamp(2010, 3, 23), advancedopenwaterdiver_id, scubalibre_id, "10040B9352");
        addDiveCertification(cristian_id, DateUtils.getTimestamp(2011, 8, 27), enrichedairdiver_id, piratasdivers_id, "1109EF8676");
        addDiveCertification(eva_id, DateUtils.getTimestamp(2008, 9, 7), scubadiver_id, redsailsports_id, "0809012500");
        addDiveCertification(eva_id, DateUtils.getTimestamp(2009, 10, 11), openwaterdiver_id, subsiluet_id, "0910EA7733");
        long eva_certification_id = addDiveCertification(eva_id, DateUtils.getTimestamp(2010, 3, 23), advancedopenwaterdiver_id, scubalibre_id, "10040B9345");
        addDiveCertification(eva_id, DateUtils.getTimestamp(2011, 8, 27), enrichedairdiver_id, piratasdivers_id, "1109EF8679");
        setDiverCertification(cristian_id, cristian_certification_id);
        setDiverCertification(eva_id, eva_certification_id);
        long eva_buddyid = addDiveBuddy("Eva", eva_id);
        long cristian_buddyid = addDiveBuddy("Cristian", cristian_id);
        long asturiano_id = addDiveBuddy("El Asturiano", null);
        long celine_id = addDiveBuddy("Celine", null);
        addDive(DateUtils.getTimestamp(2008, 9, 6, 13, 30, 0), 1560, pedernales_id, cristian_id, null, 8.0, 8.0, null, null, null, null, 207, 138, 5.0, 21, eva_buddyid, aruba_tripid, "Divemaster: Sierra Arends (Instructora) Características: Salada, Corriente, Barco Traje: Bañador Habilidades flexibles de buceo: Eliminación de calambres, Remolque de buceador cansado, Intercambio de tubo de respiración/regulador, Retirar/reemplazar scuba (superficie), Retirar/reemplazar lastre (superficie) Comentarios: Pecio Pedernales cerca de la costa de Palm Beach en Aruba. Instructora: Siierra, otros alumnos: Eva, Gerard/Nynke. Escuela: Red Sail Sports");
        addDive(DateUtils.getTimestamp(2008, 9, 7, 16, 0, 0), 3300, pedernales_id, cristian_id, 93840, 8.0, 8.0, null, null, null, null, 207, 52, 5.0, 21, eva_buddyid, aruba_tripid, "Divemaster: Jerry van Daalen (Instructor) Características: Salada, Corriente, Barco Traje: Bañador Habilidades flexibles de buceo: Retirar/reemplazar lastre (superficie) Comentarios: Instructor: Jerry (juglejerry@hotmail.com). Mismo lugar que inmersión 1. ¡HEMOS VISTO UNA TORTUGA MARINA! Ejercicios: Máscara medio llena, máscara llena, fuente de aire alternativa (sin/con remolque), flotabilidad sobre aletas Tras esta inmersión recibimos el título de Scuba Diver");
        addDive(DateUtils.getTimestamp(2009, 9, 1, 10, 0, 0), 2400, crater_id, cristian_id, null, 11.0, 11.0, 26, 24, 24, null, 200, 40, 5.0, 21, eva_buddyid, islamauricio_tripid, "Divemaster: Gilbert Luximon Características: Salada, Barco Traje: Shorty 3mm Peces: Moorish idol, Lunartail trout, Yellowtail surgeonfish, Reticulated damsel, Footballer, Forceps butterflyfish");
        addDive(DateUtils.getTimestamp(2009, 9, 2, 10, 0, 0), 2760, turtlecave_id, cristian_id, 84000, 15.0, 15.0, 26, 24, 24, null, 200, 40, 5.0, 21, asturiano_id, islamauricio_tripid, "Divemaster: Kailash Aubeeluck (nº 78887) Características: Salada, Barco Traje: Shorty 3mm Comentarios: Eva no se encuentra bien y se queda en el barco");
        addDive(DateUtils.getTimestamp(2009, 9, 4, 10, 0, 0), 2100, emilyreef_id, cristian_id, 170040, 19.0, 19.0, 26, 24, 24, null, 200, 50, 5.0, 21, eva_buddyid, islamauricio_tripid, "Divemaster: Kailash Aubeeluck (nº 78887) Características: Salada, Barco Traje: Shorty 3mm Comentarios: Kailash lleva a Eva de la mano. Kailash da de comer a los peces");
        addDive(DateUtils.getTimestamp(2009, 10, 11, 12, 0, 0), 2400, lavirgen_id, cristian_id, null, 18.0, 18.0, null, null, null, null, 200, 50, 10.0, 21, eva_buddyid, null, "Divemaster: Oscar Llobera (Instructor) Características: Salada, Barco Traje: Largo 5mm Comentarios: Una virgen dejada por los marineros da nombre a esta inmersión Ejercicios: Recuperar regulador, máscara media llena y nadar sin máscara Tras esta inmersión recibimos el título de Open Water Diver");
        addDive(DateUtils.getTimestamp(2010, 3, 23, 13, 48, 16), 2625, chunzumbul_id, cristian_id, null, 9.9, 7.5, 26, 26, 26, 12, 207, 55, 10.0, 21, eva_buddyid, playadelcarmen_tripid, null);
        addDive(DateUtils.getTimestamp(2010, 3, 23, 14, 57, 18), 2443, jardines_id, cristian_id, 1500, 11.5, 8.7, 27, 26, 26, 12, 207, 69, 10.0, 21, eva_buddyid, playadelcarmen_tripid, null);
        addDive(DateUtils.getTimestamp(2010, 3, 24, 12, 22, 40), 1764, santarosa_id, cristian_id, 74640, 22.2, 14.6, 27, 26, 26, 12, 200, 50, 10.0, 21, eva_buddyid, playadelcarmen_tripid, null);
        addDive(DateUtils.getTimestamp(2010, 3, 24, 13, 51, 8), 2575, chankanaab_id, cristian_id, 3540, 12.8, 10.1, 27, 26, 26, 12, 200, 50, 10.0, 21, eva_buddyid, playadelcarmen_tripid, null);
        addDive(DateUtils.getTimestamp(2010, 3, 25, 11, 8, 40), 2557, kukulkan_id, cristian_id, 74040, 13.4, 8.0, 25, 25, 27, 12, 210, 100, 6.0, 21, eva_buddyid, playadelcarmen_tripid, null);
        addDive(DateUtils.getTimestamp(2010, 3, 25, 13, 3, 32), 3520, chacmool_id, cristian_id, 4320, 12.28, 6.59, 25, 25, 26, 12, 200, 90, 6.0, 21, eva_buddyid, playadelcarmen_tripid, null);
        addDive(DateUtils.getTimestamp(2010, 3, 26, 9, 19, 1), 1950, mamavinya_id, cristian_id, 69420, 26.8, 18.8, 28, 27, 26, 12, 210, 50, 11.0, 21, eva_buddyid, playadelcarmen_tripid, null);
        addDive(DateUtils.getTimestamp(2010, 3, 26, 10, 24, 10), 2822, sabalos_id, cristian_id, 1920, 14.2, 10.1, 28, 27, 27, 12, 210, 40, 11.0, 21, eva_buddyid, playadelcarmen_tripid, null);
        addDive(DateUtils.getTimestamp(2010, 3, 27, 9, 9, 39), 2643, tortugas_id, cristian_id, 79080, 19.7, 14.0, 28, 26, 26, 12, 200, 50, 10.0, 21, eva_buddyid, playadelcarmen_tripid, null);
        addDive(DateUtils.getTimestamp(2010, 3, 27, 10, 22, 0), 2965, barracuda_id, cristian_id, 1680, 13.4, 9.8, 28, 27, 26, 12, 210, 50, 10.0, 21, eva_buddyid, playadelcarmen_tripid, null);
        addDive(DateUtils.getTimestamp(2010, 6, 20, 12, 1, 41), 2610, barretadelarbre_id, cristian_id, null, 20.1, 16.1, 21, 19, 17, 12, 200, 50, 10.0, 21, eva_buddyid, null, "Algún que otro pez de color, pero en general poca cosa. Una Escórpora escondida a la ida y otra a la vuelta. Alguna estrellita de mar. Estrenamos regulador y jacket y por primera vez he hecho unas fotos. Como siempre, mareo en el barco.");
        addDive(DateUtils.getTimestamp(2010, 6, 25, 10, 18, 21), 1697, larbre_id, cristian_id, null, 20.4, 16.7, 18, 15, 13, 12, 190, 40, 12.0, 21, celine_id, capdagde_tripid, "Eva pierde una aleta y entre esto y el frío decide no bajar. Yo bajo con la divemaster Celine y 2 más. Hay bastante corriente en superficie, pero bajo el agua casi nada. La visibilidad es extremadamente mala, y necesito mantenerme a menos de un metro de la divemaster para no perderme. Encima de esto, el agua está extremadamente fría (13 grados), por lo que acabo gastando mi aire en un tiempo record. Para alargar un poco la inmersión, Celine me hace usar su octopus durante unos minutos. En toda la inmersión sólo veo una Escórpora y una Langosta escondidos en la roca. Decidimos no repetir el día siguiente.");
        addDive(DateUtils.getTimestamp(2010, 8, 1, 17, 29, 25), 2111, marmenuda_id, cristian_id, null, 14.8, 6.0, 25, 24, 23, 12, 200, 100, 8.0, 21, eva_buddyid, null, "Bautismo de Jordi. Nos acompaña su hermano Marcel, y también Sonia y Anna. Una ruta muy bonita entre rocas, y mucho más peces de lo que estamos acostumbrados en el Mar Mediterráneo.");
        addDive(DateUtils.getTimestamp(2010, 8, 31, 15, 13, 24), 2464, jetty_id, cristian_id, null, 17.6, 10.0, 32, 30, 29, 12, 200, 50, 8.0, 21, eva_buddyid, lankayan_tripid, "El check dive del día de llegada. Desde el jetty con paso gigante. Visibilidad regulin y poco más que ver que 3 peces león en una especie de columna de malla. El fondo está lleno de pepinos de mar.");
        addDive(DateUtils.getTimestamp(2010, 9, 1, 8, 32, 40), 2673, kensrock_id, cristian_id, 59880, 21.1, 13.8, 30, 30, 29, 12, 200, 50, 8.0, 21, eva_buddyid, lankayan_tripid, "Entrada de espaldas desde el barco, bajada por el cabo. Reunión abajo y luego vuelta alrededor del montículo, para acabar encima. Muchos peces de arrecife y una cantidad increíble de \"vegetación\".");
        addDive(DateUtils.getTimestamp(2010, 9, 1, 11, 32, 9), 3016, southrock_id, cristian_id, 8040, 17.9, 10.5, 31, 30, 29, 12, 200, 50, 8.0, 21, eva_buddyid, lankayan_tripid, "Similar a Ken's Rock, nos acabamos agobiando bastante con el resto del grupo (aletazos). Por fin veo anémonas con sus habitantes habituales, los peces payaso.");
        addDive(DateUtils.getTimestamp(2010, 9, 2, 8, 31, 18), 2256, lostworld_id, cristian_id, 72480, 25.6, 15.8, 31, 30, 29, 12, 200, 40, 8.0, 21, eva_buddyid, lankayan_tripid, "Después de un diluvio nocturno, amanece nublado, pero con el mar como un espejo. Nos pasan al grupo avanzado. Lost World se llama así porque llegaron a \"perderlo\" antes de encontrarlo de nuevo. Justo al bajar vemos un ENORME TIBURÓN. Por lo demás, lo bonito es la vegetación y algún pez angel y el pez loro que solemos ver haciendo snorkel. Hacemos la parada de seguridad Eva y yo solos.");
        addDive(DateUtils.getTimestamp(2010, 9, 2, 11, 28, 23), 2759, billysreef_id, cristian_id, 8340, 22.6, 14.7, 31, 30, 30, 12, 200, 50, 8.0, 21, eva_buddyid, lankayan_tripid, "La segunda inmersión del día es similar a la primera. Con el grupo avanzado todo va más \"sobre ruedas\". Peces payaso (¿padre e hijo?). Un pez enorme no identificado. Nos sobresaltamos con un ruido fuerte, que resulta ser pescadores con dinamita a unos 4-5km. La visibilidad al fondo no es muy buena pero encima está mejor.");
        addDive(DateUtils.getTimestamp(2010, 9, 2, 15, 25, 17), 2760, raycity_id, cristian_id, 11400, 19.7, 11.0, 32, 30, 30, 12, 200, 50, 8.0, 21, eva_buddyid, lankayan_tripid, "Por primera vez hacemos 3 inmersiones en el mismo día, y además es mi 25º. Mucha corriente, lo cual agobia un poco.");
        addDive(DateUtils.getTimestamp(2010, 9, 3, 8, 39, 43), 2636, sunnuglair_id, cristian_id, 59280, 22.4, 16.8, 31, 31, 30, 12, 200, 50, 8.0, 21, eva_buddyid, lankayan_tripid, "Nos avisan de mala visibilidad, pero no es más que regular. Nada especial que mencionar, cada vez vamos aprendiendo un poco más.");
        addDive(DateUtils.getTimestamp(2010, 9, 3, 11, 38, 39), 2891, gobyrock_id, cristian_id, 8100, 20.1, 14.3, 31, 31, 29, 12, 200, 50, 8.0, 21, eva_buddyid, lankayan_tripid, "Por encima de la roca un montón de peces, una anémona con al menos 3 peces payaso. Bajamos hasta el fondo que es menos espectacular. Fotografío un pez león y un nudibranqueo. . Cuando queda 60bar, con la corriente que hay, decidimos subir.");
        addDive(DateUtils.getTimestamp(2010, 9, 3, 15, 33, 38), 3020, andyant_id, cristian_id, 11160, 18.4, 12.6, 31, 31, 30, 12, 200, 40, 8.0, 21, eva_buddyid, lankayan_tripid, "Hoy ha sido \"el día de la tortuga\" ya que anoche vimos a una tortuga poniendo huevos, hoy vimos como se soltaron las tortuguitas recién nacidas, y en esta inmersión vimos 2 (o 1 dos veces) tortugas. Uno de los guías nos llevó a la cima del arrecife donde hay muchísimos más peces.");
        addDive(DateUtils.getTimestamp(2010, 9, 4, 8, 31, 17), 2760, lostreef_id, cristian_id, 58020, 24.2, 17.2, 31, 30, 29, 12, 200, 50, 8.0, 21, eva_buddyid, lankayan_tripid, "Tras irse casi todo el mundo, esta inmersión la hacemos con Ruggero y un chico Inglés. La inmersión bastante similar a las anteriores. Vemos una tortuga y una langosta.");
        addDive(DateUtils.getTimestamp(2010, 9, 4, 11, 27, 52), 2709, jawfishlair_id, cristian_id, 7800, 21.2, 15.5, 31, 31, 29, 12, 200, 50, 8.0, 21, eva_buddyid, lankayan_tripid, "Pareció ser la más aburrida de todas y resultó ser una de las más chulas. El chico Inglés se desapuntó así que sólo eramos 3. Nos pasamos 20 minutos en el barro y parecía que no encontrábamos el arrecife. Cuando lo encontramos vimos un tiburón de arrecife de punta negra de más de 1 metro, 12 rayas juntas y el momento más espectacular: 4 peces loro \"bump head\" INMENSOS dando vueltas. ¡ESPECTACULAR!");
        addDive(DateUtils.getTimestamp(2010, 9, 4, 15, 28, 11), 3020, melsrock_id, cristian_id, 11700, 18.2, 13.3, 32, 31, 30, 12, 200, 50, 8.0, 21, eva_buddyid, lankayan_tripid, "Eva y yo somos los únicos aunque al final nos acompañan 2 chicas del centro de tortugas. Vemos varios peces león, una tortuga peque pero de muy cerca, montones de peces payaso y un sinfin de peces de arrecife. Al final un poco de corriente, si no quizás aún hubiesemos aguantado aún más tiempo.");
        addDive(DateUtils.getTimestamp(2010, 9, 5, 8, 30, 11), 2815, lostreef_id, cristian_id, 58260, 24.0, 17.7, 31, 31, 29, 12, 200, 40, 8.0, 21, eva_buddyid, lankayan_tripid, "Para la última inmersión de Ruggero quería volver a \"Lost Reef\" para ver si encontrábamos el \"Octopus Maravilla\" que vimos (bueno, que vió el guía) la primera vez. No hubo suerte. Lo que sí vimos fue una sepia que cambiaba de color dependiendo de dónde nadaba.");
        addDive(DateUtils.getTimestamp(2010, 9, 5, 11, 24, 48), 2982, malumalu_id, cristian_id, 7620, 20.1, 13.4, 31, 31, 29, 12, 200, 50, 8.0, 21, eva_buddyid, lankayan_tripid, "Esta vez sí que hemos ido completamente solos (yo, Eva y el guía). Han sido 2 partes: Primero un arrecife bastante plano, que hemos rodeado, y luego un banco de arena muy muy luminoso con islitas de coral. Todos los sospechosos habituales han estado presentes: Nudibranqueos, rayas y peces de todo tipo.");
        addDive(DateUtils.getTimestamp(2010, 9, 5, 15, 32, 24), 3292, ikohsrock_id, cristian_id, 11820, 18.7, 12.9, 31, 31, 30, 12, 200, 50, 8.0, 21, eva_buddyid, lankayan_tripid, "Un día nublado prometía una inmersión regular, pero nada más lejos de la verdad. Hico fotos chulas de peces león, nudibranqueos, y peces payaso, pero las estrellas de la inmersión fueron los enormes TIBURONES LEOPARDO (tamaño persona). También vimos un pez muy raro: Juvenile Batfish.");
        addDive(DateUtils.getTimestamp(2010, 9, 6, 8, 42, 9), 2900, fanrock_id, cristian_id, 58440, 21.9, 15.4, 31, 30, 30, 12, 200, 50, 8.0, 21, eva_buddyid, lankayan_tripid, "Otro día nublado, pero con una buena inmersión. Vemos 2 tortugas, una desde muy cerca durante mucho rato porque estaba comiendo. Por lo demás como siempre muchísimos peces y una vegetación preciosa. Ultima inmersión en Lankayan ya que mañana a las 11:35 cogemos el avión y hay que desaturar 24 horas.");
        addDive(DateUtils.getTimestamp(2011, 4, 12, 11, 4, 15), 3113, housereef_id, cristian_id, null, 20.02, 9.36, 31, 30, 30, 12, 200, 50, 6.0, 21, eva_buddyid, kuredu_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 4, 12, 15, 31, 29), 3094, medadihuraoutreef_id, cristian_id, 12900, 21.02, 12.02, 32, 31, 29, 12, 200, 50, 6.0, 21, eva_buddyid, kuredu_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 4, 13, 10, 12, 39), 3273, anumonethila_id, cristian_id, 64140, 20.98, 14.76, 32, 30, 30, 12, 200, 50, 6.0, 21, eva_buddyid, kuredu_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 4, 13, 12, 25, 35), 3368, kureduexpress_id, cristian_id, 4680, 20.76, 12.55, 32, 30, 29, 12, 200, 50, 6.0, 21, eva_buddyid, kuredu_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 4, 13, 15, 41, 53), 3053, housereef_id, cristian_id, 8400, 21.67, 13.16, 31, 30, 30, 12, 200, 50, 6.0, 21, eva_buddyid, kuredu_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 4, 14, 10, 6, 5), 3602, madivaruthila_id, cristian_id, 63180, 17.96, 10.06, 31, 30, 30, 12, 200, 50, 6.0, 21, eva_buddyid, kuredu_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 4, 14, 12, 42, 6), 3597, kureducaves_id, cristian_id, 5700, 20.04, 11.82, 33, 30, 30, 12, 200, 50, 6.0, 21, eva_buddyid, kuredu_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 4, 14, 15, 25, 43), 3188, housereef_id, cristian_id, 6180, 18.22, 10.7, 31, 30, 30, 12, 200, 50, 6.0, 21, eva_buddyid, kuredu_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 4, 15, 10, 7, 10), 3309, kffc_id, cristian_id, 64080, 27.5, 15.3, 32, 30, 30, 12, 200, 50, 6.0, 21, eva_buddyid, kuredu_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 4, 15, 15, 21, 27), 3366, ismaelsthila_id, cristian_id, 15540, 20.72, 13.36, 36, 30, 30, 12, 200, 50, 6.0, 21, eva_buddyid, kuredu_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 4, 15, 17, 30, 5), 3698, thewall_id, cristian_id, 4320, 14.49, 9.63, 33, 30, 30, 12, 200, 50, 6.0, 21, eva_buddyid, kuredu_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 4, 16, 9, 51, 37), 2991, fushivaruthila_id, cristian_id, 55140, 23.52, 15.07, 32, 30, 30, 12, 200, 50, 6.0, 21, eva_buddyid, kuredu_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 4, 16, 11, 56, 36), 3256, nakolhothila_id, cristian_id, 4440, 22.49, 12.69, 31, 30, 30, 12, 200, 50, 6.0, 21, eva_buddyid, kuredu_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 4, 16, 15, 18, 31), 3605, tingagiri_id, cristian_id, 8820, 20.26, 11.4, 32, 31, 30, 12, 200, 50, 6.0, 21, eva_buddyid, kuredu_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 4, 17, 9, 39, 6), 3378, latheefreef_id, cristian_id, 62400, 22.4, 13.6, 37, 30, 30, 12, 200, 50, 6.0, 21, eva_buddyid, kuredu_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 4, 17, 11, 51, 8), 3686, aaagiri_id, cristian_id, 4500, 19.37, 11.76, 32, 30, 30, 12, 200, 70, 6.0, 21, eva_buddyid, kuredu_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 8, 21, 10, 7, 54), 2921, abril_id, cristian_id, null, 21.84, 17.28, 25, 24, 20, 12, 200, 50, 8.0, 32, eva_buddyid, null, null);
        addDive(DateUtils.getTimestamp(2011, 8, 21, 12, 17, 0), 2619, milanas_id, cristian_id, 4800, 18.66, 13.48, 27, 24, 21, 12, 200, 50, 6.0, 32, eva_buddyid, null, null);
        addDive(DateUtils.getTimestamp(2011, 9, 1, 9, 47, 9), 2999, germanchannel_id, cristian_id, null, 19.88, 13.18, 31, 30, 30, 12, 180, 50, 6.0, 32, eva_buddyid, palau_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 9, 1, 12, 29, 37), 2833, blueholes_id, cristian_id, 6720, 25.35, 15.69, 31, 30, 29, 12, 200, 50, 6.0, 32, eva_buddyid, palau_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 9, 2, 10, 1, 17), 3676, virginbluehole_id, cristian_id, 74640, 32.08, 16.5, 31, 30, 29, 12, 200, 30, 6.0, 32, eva_buddyid, palau_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 9, 2, 12, 1, 37), 3244, bigdropoff_id, cristian_id, 3540, 26.39, 13.04, 31, 30, 29, 12, 200, 70, 6.0, 32, eva_buddyid, palau_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 9, 2, 16, 46, 6), 2300, jakeseaplane_id, cristian_id, 7740, 12.63, 10.01, 30, 30, 30, 12, 200, 130, 6.0, 31, eva_buddyid, palau_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 9, 3, 9, 46, 25), 3656, ulongchannel_id, cristian_id, 58860, 16.44, 11.37, 31, 30, 30, 12, 200, 60, 6.0, 32, eva_buddyid, palau_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 9, 3, 12, 5, 26), 3875, ulongwall_id, cristian_id, 4680, 18.83, 12.71, 30, 30, 30, 12, 200, 60, 6.0, 32, eva_buddyid, palau_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 9, 3, 15, 41, 15), 2589, helmetwreck_id, cristian_id, 9060, 24.84, 14.76, 31, 30, 30, 12, 200, 70, 6.0, 32, eva_buddyid, palau_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 9, 4, 9, 55, 46), 3339, ngerchongoutside_id, cristian_id, 63060, 25.0, 15.23, 29, 29, 29, 12, 200, 60, 6.0, 32, eva_buddyid, palau_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 9, 4, 11, 55, 14), 4271, ngerchonginside_id, cristian_id, 3780, 25.61, 12.42, 30, 30, 29, 12, 200, 50, 6.0, 32, eva_buddyid, palau_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 9, 4, 15, 12, 36), 2610, chandeliercave_id, cristian_id, 7560, 10.7, 6.22, 30, 30, 30, 12, 200, 160, 6.0, 32, eva_buddyid, palau_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 9, 5, 10, 33, 1), 3625, bluecorner_id, cristian_id, 66960, 23.22, 12.17, 30, 30, 29, 12, 200, 50, 6.0, 32, eva_buddyid, palau_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 9, 5, 12, 45, 19), 3795, germanchannel_id, cristian_id, 4260, 25.46, 14.23, 31, 30, 30, 12, 200, 50, 6.0, 32, eva_buddyid, palau_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 9, 5, 15, 33, 9), 3688, ngedbuswall_id, cristian_id, 6240, 21.34, 13.81, 31, 30, 30, 12, 200, 50, 6.0, 32, eva_buddyid, palau_tripid, null);
        addDive(DateUtils.getTimestamp(2008, 9, 6, 13, 30, 0), 1560, pedernales_id, eva_id, null, 8.0, 8.0, null, null, null, null, 207, 138, 4.0, 21, cristian_buddyid, aruba_tripid, null);
        addDive(DateUtils.getTimestamp(2008, 9, 7, 16, 0, 0), 3300, pedernales_id, eva_id, 93840, 8.0, 8.0, null, null, null, null, 207, 103, 4.5, 21, cristian_buddyid, aruba_tripid, null);
        addDive(DateUtils.getTimestamp(2009, 9, 1, 10, 0, 0), 2400, crater_id, eva_id, null, 11.0, 11.0, 26, 24, 24, null, 200, 90, 5.0, 21, cristian_buddyid, islamauricio_tripid, null);
        addDive(DateUtils.getTimestamp(2009, 9, 4, 10, 0, 0), 3540, emilyreef_id, eva_id, 256800, 19.0, 19.0, 26, 24, 24, null, 200, 50, 5.0, 21, cristian_buddyid, islamauricio_tripid, null);
        addDive(DateUtils.getTimestamp(2009, 10, 11, 12, 0, 0), 2400, lavirgen_id, eva_id, null, 18.0, 18.0, null, null, null, null, 200, 70, 8.0, 21, cristian_buddyid, null, null);
        addDive(DateUtils.getTimestamp(2010, 3, 23, 13, 47, 45), 2628, chunzumbul_id, eva_id, null, 10.04, 8.02, 26, 26, 26, 12, 200, 90, 9.0, 21, cristian_buddyid, playadelcarmen_tripid, null);
        addDive(DateUtils.getTimestamp(2010, 3, 23, 14, 56, 45), 2420, jardines_id, eva_id, 1500, 12.17, 8.89, 26, 26, 26, 12, 200, 80, 9.0, 21, cristian_buddyid, playadelcarmen_tripid, null);
        addDive(DateUtils.getTimestamp(2010, 3, 24, 12, 22, 22), 1751, santarosa_id, eva_id, 74700, 21.84, 14.67, 27, 26, 26, 12, 200, 90, 9.0, 21, cristian_buddyid, playadelcarmen_tripid, null);
        addDive(DateUtils.getTimestamp(2010, 3, 24, 13, 51, 21), 2556, chankanaab_id, eva_id, 3540, 13.25, 10.49, 27, 26, 26, 12, 200, 80, 9.0, 21, cristian_buddyid, playadelcarmen_tripid, null);
        addDive(DateUtils.getTimestamp(2010, 3, 25, 11, 8, 11), 2523, kukulkan_id, eva_id, 74040, 13.64, 8.33, 25, 25, 27, 12, 200, 100, 6.0, 21, cristian_buddyid, playadelcarmen_tripid, null);
        addDive(DateUtils.getTimestamp(2010, 3, 25, 13, 3, 5), 3420, chacmool_id, eva_id, 4320, 12.66, 7.05, 25, 25, 26, 12, 200, 100, 6.0, 21, cristian_buddyid, playadelcarmen_tripid, null);
        addDive(DateUtils.getTimestamp(2010, 3, 26, 9, 19, 1), 1941, mamavinya_id, eva_id, 69540, 27.12, 19.03, 27, 26, 26, 12, 210, 60, 8.0, 21, cristian_buddyid, playadelcarmen_tripid, null);
        addDive(DateUtils.getTimestamp(2010, 3, 26, 10, 23, 53), 2814, sabalos_id, eva_id, 1920, 13.97, 10.32, 27, 26, 26, 12, 210, 120, 8.0, 21, cristian_buddyid, playadelcarmen_tripid, null);
        addDive(DateUtils.getTimestamp(2010, 3, 27, 9, 10, 2), 2611, tortugas_id, eva_id, 79140, 19.81, 14.53, 27, 26, 26, 12, 210, 70, 9.0, 21, cristian_buddyid, playadelcarmen_tripid, null);
        addDive(DateUtils.getTimestamp(2010, 3, 27, 10, 22, 0), 2978, barracuda_id, eva_id, 1680, 13.95, 10.11, 27, 26, 26, 12, 210, 70, 9.0, 21, cristian_buddyid, playadelcarmen_tripid, null);
        addDive(DateUtils.getTimestamp(2010, 6, 20, 12, 1, 5), 2625, barretadelarbre_id, eva_id, null, 21.3, 16.1, 20, 18, 17, 12, 200, 60, 8.0, 21, cristian_buddyid, null, null);
        addDive(DateUtils.getTimestamp(2010, 8, 1, 17, 28, 40), 2120, marmenuda_id, eva_id, null, 15.27, 6.4, 25, 23, 22, 12, 220, 100, 8.0, 21, cristian_buddyid, null, null);
        addDive(DateUtils.getTimestamp(2010, 8, 31, 15, 13, 40), 2318, jetty_id, eva_id, null, 17.66, 10.67, 32, 31, 29, 12, null, null, 6.0, 21, cristian_buddyid, lankayan_tripid, null);
        addDive(DateUtils.getTimestamp(2010, 9, 1, 8, 33, 0), 2682, kensrock_id, eva_id, 59940, 20.2, 13.65, 30, 30, 29, 12, 190, 60, 6.0, 21, cristian_buddyid, lankayan_tripid, null);
        addDive(DateUtils.getTimestamp(2010, 9, 1, 11, 32, 22), 3013, southrock_id, eva_id, 8040, 18.71, 10.35, 30, 30, 29, 12, 210, 80, 6.0, 21, cristian_buddyid, lankayan_tripid, null);
        addDive(DateUtils.getTimestamp(2010, 9, 2, 8, 31, 23), 2265, lostworld_id, eva_id, 72480, 26.5, 15.65, 30, 30, 29, 12, 200, 70, 6.0, 21, cristian_buddyid, lankayan_tripid, null);
        addDive(DateUtils.getTimestamp(2010, 9, 2, 11, 28, 46), 2750, billysreef_id, eva_id, 8340, 24.09, 14.26, 31, 31, 29, 12, 200, 70, 6.0, 21, cristian_buddyid, lankayan_tripid, null);
        addDive(DateUtils.getTimestamp(2010, 9, 2, 15, 25, 37), 2749, raycity_id, eva_id, 11460, 20.15, 10.55, 32, 31, 29, 12, 210, 80, 6.0, 21, cristian_buddyid, lankayan_tripid, null);
        addDive(DateUtils.getTimestamp(2010, 9, 3, 8, 40, 4), 2630, sunnuglair_id, eva_id, 59280, 22.97, 16.85, 31, 31, 29, 12, 210, 60, 6.0, 21, cristian_buddyid, lankayan_tripid, null);
        addDive(DateUtils.getTimestamp(2010, 9, 3, 11, 38, 49), 2899, gobyrock_id, eva_id, 8040, 20.85, 14.18, 31, 31, 29, 12, 200, 70, 6.0, 21, cristian_buddyid, lankayan_tripid, null);
        addDive(DateUtils.getTimestamp(2010, 9, 3, 15, 33, 44), 3028, andyant_id, eva_id, 11160, 18.28, 12.25, 32, 31, 30, 12, 200, 60, 6.0, 21, cristian_buddyid, lankayan_tripid, null);
        addDive(DateUtils.getTimestamp(2010, 9, 4, 8, 31, 27), 2768, lostreef_id, eva_id, 58020, 24.35, 17.13, 31, 31, 29, 12, 200, 50, 6.0, 21, cristian_buddyid, lankayan_tripid, null);
        addDive(DateUtils.getTimestamp(2010, 9, 4, 11, 28, 12), 2705, jawfishlair_id, eva_id, 7800, 21.52, 15.61, 31, 31, 29, 12, 210, 40, 6.0, 21, cristian_buddyid, lankayan_tripid, null);
        addDive(DateUtils.getTimestamp(2010, 9, 4, 15, 28, 27), 3019, melsrock_id, eva_id, 11700, 18.22, 13.3, 32, 31, 30, 12, 210, 50, 5.5, 21, cristian_buddyid, lankayan_tripid, null);
        addDive(DateUtils.getTimestamp(2010, 9, 5, 8, 30, 32), 2801, lostreef_id, eva_id, 58260, 24.99, 17.36, 32, 31, 30, 12, 200, 50, 5.5, 21, cristian_buddyid, lankayan_tripid, null);
        addDive(DateUtils.getTimestamp(2010, 9, 5, 11, 24, 48), 2993, malumalu_id, eva_id, 7620, 19.56, 13.65, 31, 31, 29, 12, 200, 50, 5.5, 21, cristian_buddyid, lankayan_tripid, null);
        addDive(DateUtils.getTimestamp(2010, 9, 5, 15, 32, 39), 3315, ikohsrock_id, eva_id, 11820, 18.91, 12.87, 31, 31, 30, 12, 200, 60, 5.5, 21, cristian_buddyid, lankayan_tripid, null);
        addDive(DateUtils.getTimestamp(2010, 9, 6, 8, 42, 27), 2882, fanrock_id, eva_id, 58440, 21.34, 15.29, 31, 30, 30, 12, 200, 70, 5.5, 21, cristian_buddyid, lankayan_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 4, 12, 11, 4, 30), 3081, housereef_id, eva_id, null, 20.33, 9.26, 31, 30, 30, 12, 210, 70, 5.0, 21, cristian_buddyid, kuredu_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 4, 12, 15, 31, 30), 3093, medadihuraoutreef_id, eva_id, 12900, 20.92, 12.29, 32, 31, 29, 12, 200, 60, 6.0, 21, cristian_buddyid, kuredu_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 4, 13, 10, 12, 42), 3267, anumonethila_id, eva_id, 64140, 20.4, 14.66, 32, 30, 30, 12, 195, 55, 6.0, 21, cristian_buddyid, kuredu_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 4, 13, 12, 25, 27), 3376, kureduexpress_id, eva_id, 4680, 20.31, 12.7, 31, 30, 29, 12, 200, 60, 6.0, 21, cristian_buddyid, kuredu_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 4, 13, 15, 41, 41), 3069, housereef_id, eva_id, 8340, 22.72, 13.05, 32, 30, 30, 12, 200, 50, 6.0, 21, cristian_buddyid, kuredu_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 4, 14, 10, 6, 8), 3598, madivaruthila_id, eva_id, 63180, 17.65, 9.84, 30, 30, 30, 12, 200, 60, 6.0, 21, cristian_buddyid, kuredu_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 4, 14, 12, 41, 56), 3607, kureducaves_id, eva_id, 5700, 18.57, 12.13, 32, 30, 30, 12, 200, 60, 6.0, 21, cristian_buddyid, kuredu_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 4, 14, 15, 25, 12), 3216, housereef_id, eva_id, 6180, 18.56, 9.94, 31, 30, 30, 12, 195, 70, 5.0, 21, cristian_buddyid, kuredu_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 4, 15, 10, 7, 11), 3330, kffc_id, eva_id, 64080, 26.9, 15.44, 31, 30, 30, 12, 200, 50, 6.0, 21, cristian_buddyid, kuredu_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 4, 15, 15, 21, 25), 3383, ismaelsthila_id, eva_id, 15480, 20.12, 13.24, 33, 30, 30, 12, 200, 45, 6.0, 21, cristian_buddyid, kuredu_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 4, 15, 17, 29, 55), 3696, thewall_id, eva_id, 4320, 15.54, 10.25, 31, 30, 30, 12, 200, 50, 6.0, 21, cristian_buddyid, kuredu_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 4, 16, 9, 51, 37), 3025, fushivaruthila_id, eva_id, 55200, 25.58, 15.51, 33, 30, 30, 12, 200, 50, 6.0, 21, cristian_buddyid, kuredu_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 4, 16, 11, 56, 32), 3291, nakolhothila_id, eva_id, 4440, 24.13, 12.85, 31, 30, 30, 12, 200, 50, 6.0, 21, cristian_buddyid, kuredu_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 4, 16, 15, 18, 28), 3613, tingagiri_id, eva_id, 8760, 18.1, 11.64, 32, 31, 30, 12, 200, 55, 6.0, 21, cristian_buddyid, kuredu_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 4, 17, 9, 38, 58), 3399, latheefreef_id, eva_id, 62400, 21.99, 14.25, 33, 31, 30, 12, 200, 60, 6.0, 21, cristian_buddyid, kuredu_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 4, 17, 11, 51, 2), 3688, aaagiri_id, eva_id, 4500, 17.66, 11.35, 31, 30, 30, 12, 200, 50, 6.0, 21, cristian_buddyid, kuredu_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 8, 21, 10, 7, 40), 2904, abril_id, eva_id, null, 23.22, 16.82, 25, 24, 23, 12, 210, 40, 6.0, 32, cristian_buddyid, null, null);
        addDive(DateUtils.getTimestamp(2011, 8, 21, 12, 16, 38), 2630, milanas_id, eva_id, 4800, 17.53, 12.3, 26, 24, 21, 12, 220, 90, 4.0, 32, cristian_buddyid, null, null);
        addDive(DateUtils.getTimestamp(2011, 9, 1, 9, 48, 31), 2869, germanchannel_id, eva_id, null, 19.48, 13.19, 30, 30, 30, 12, 200, 35, 6.0, 32, cristian_buddyid, palau_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 9, 1, 12, 29, 29), 2847, blueholes_id, eva_id, 6780, 24.91, 16.1, 31, 30, 30, 12, 200, 50, 8.0, 32, cristian_buddyid, palau_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 9, 2, 10, 0, 55), 3710, virginbluehole_id, eva_id, 74580, 31.46, 16.98, 30, 30, 29, 12, 200, 50, 7.0, 32, cristian_buddyid, palau_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 9, 2, 12, 1, 16), 3245, bigdropoff_id, eva_id, 3480, 26.0, 12.88, 31, 31, 30, 12, 200, 50, 7.0, 32, cristian_buddyid, palau_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 9, 2, 16, 45, 12), 2332, jakeseaplane_id, eva_id, 13740, 11.07, 8.59, 30, 30, 30, 12, 210, 130, 7.0, 32, cristian_buddyid, palau_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 9, 3, 9, 46, 1), 3669, ulongchannel_id, eva_id, 58860, 16.4, 11.61, 31, 30, 30, 12, 200, 60, 7.0, 32, cristian_buddyid, palau_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 9, 3, 12, 5, 12), 3896, ulongwall_id, eva_id, 4680, 18.37, 12.25, 31, 30, 30, 12, 220, 60, 7.0, 32, cristian_buddyid, palau_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 9, 3, 15, 40, 51), 2579, helmetwreck_id, eva_id, 9000, 24.66, 14.21, 31, 30, 30, 12, 200, 100, 7.0, 32, cristian_buddyid, palau_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 9, 4, 9, 55, 25), 3347, ngerchongoutside_id, eva_id, 63060, 25.01, 15.19, 29, 29, 29, 12, 210, 60, 7.0, 32, cristian_buddyid, palau_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 9, 4, 11, 54, 51), 4276, ngerchonginside_id, eva_id, 3780, 24.64, 12.23, 30, 30, 29, 12, 200, 80, 7.0, 32, cristian_buddyid, palau_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 9, 4, 15, 12, 13), 2680, chandeliercave_id, eva_id, 7560, 11.86, 6.26, 30, 30, 30, 12, 200, 120, 7.0, 32, cristian_buddyid, palau_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 9, 5, 10, 32, 41), 3636, bluecorner_id, eva_id, 66960, 22.91, 12.3, 30, 30, 29, 12, 200, 70, 7.0, 32, cristian_buddyid, palau_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 9, 5, 12, 44, 56), 3790, germanchannel_id, eva_id, 4260, 26.04, 14.4, 30, 30, 30, 12, 200, 80, 7.0, 32, cristian_buddyid, palau_tripid, null);
        addDive(DateUtils.getTimestamp(2011, 9, 5, 15, 32, 39), 3746, ngedbuswall_id, eva_id, 6240, 21.69, 14.22, 31, 30, 30, 12, 200, 60, 7.0, 32, cristian_buddyid, palau_tripid, null);
        addDive(DateUtils.getTimestamp(2013, 10, 5, 9, 9, 12), 3030, halikreef_id, cristian_id, 145080, 21.4, 14.4, 28, 28, 28, 12, 200, 40, 6.0, 21, eva_buddyid, gilitrawangan_tripid, null);
        addDive(DateUtils.getTimestamp(2013, 10, 5, 11, 3, 43), 2958, menowall_id, cristian_id, 3780, 20.2, 13.5, 28, 28, 28, 12, 200, 70, 6.0, 21, eva_buddyid, gilitrawangan_tripid, null);
        addDive(DateUtils.getTimestamp(2013, 10, 7, 9, 11, 55), 2160, sharkpoint_id, cristian_id, 163080, 29.9, 18.7, 28, 28, 28, 12, 200, 40, 6.0, 21, eva_buddyid, gilitrawangan_tripid, null);
        addDive(DateUtils.getTimestamp(2013, 10, 7, 10, 54, 44), 2823, bountywreck_id, cristian_id, 3960, 21.0, 13.9, 28, 29, 28, 12, 200, 50, 6.0, 21, eva_buddyid, gilitrawangan_tripid, null);
        addDive(DateUtils.getTimestamp(2013, 10, 9, 9, 38, 11), 3495, secretreef_id, cristian_id, 165360, 20.4, 14.6, 28, 28, 28, 12, 200, 50, 6.0, 21, eva_buddyid, gilitrawangan_tripid, null);
        addDive(DateUtils.getTimestamp(2013, 10, 9, 11, 52, 58), 3480, menoslope_id, cristian_id, 4560, 19.8, 12.9, 28, 28, 28, 12, 200, 50, 6.0, 21, eva_buddyid, gilitrawangan_tripid, null);
        addDive(DateUtils.getTimestamp(2013, 10, 5, 9, 10, 3), 3009, halikreef_id, eva_id, null, 21.9, 14.7, 28, 28, 28, 12, 200, 70, 6.0, 21, cristian_buddyid, gilitrawangan_tripid, null);
        addDive(DateUtils.getTimestamp(2013, 10, 5, 11, 3, 42), 2976, menowall_id, eva_id, 3780, 20.3, 13.4, 28, 28, 28, 12, 200, 70, 6.0, 21, cristian_buddyid, gilitrawangan_tripid, null);
        addDive(DateUtils.getTimestamp(2013, 10, 7, 9, 12, 12), 2153, sharkpoint_id, eva_id, 163080, 28.8, 18.6, 28, 28, 28, 12, 200, 70, 6.0, 21, cristian_buddyid, gilitrawangan_tripid, null);
        addDive(DateUtils.getTimestamp(2013, 10, 7, 10, 54, 27), 2853, bountywreck_id, eva_id, 3960, 20.2, 13.8, 28, 29, 28, 12, 200, 70, 6.0, 21, cristian_buddyid, gilitrawangan_tripid, null);
        addDive(DateUtils.getTimestamp(2013, 10, 9, 9, 38, 8), 3512, secretreef_id, eva_id, 165360, 21.1, 14.6, 30, 28, 28, 12, 200, 70, 6.0, 21, cristian_buddyid, gilitrawangan_tripid, null);
        addDive(DateUtils.getTimestamp(2013, 10, 9, 11, 53, 13), 3499, menoslope_id, eva_id, 4560, 20.2, 12.3, 28, 29, 28, 12, 200, 70, 6.0, 21, cristian_buddyid, gilitrawangan_tripid, null);
    }

    private boolean setDiverCertification(long diverId, long certificationId) {
        Uri uri = Uri.withAppendedPath(DiveLogProvider.CONTENT_URI, DiveLogProvider.PATH_DIVERS);
        ContentValues values = new ContentValues();
        values.put(DiveLogDatabaseContract.Divers.COLUMN_NAME_CERTIFICATION_ID, certificationId);
        String selection = DiveLogDatabaseContract.Divers._ID + " = ?";
        String[] selectionArgs = {Long.toString(diverId)};
        int count = mResolver.update(
                uri,
                values,
                selection,
                selectionArgs);
        return (count == 1);
    }

    private void DELETEDATABASE(Context context) {
        context.deleteDatabase(DiveLogDatabaseContract.DATABASE_NAME);
    }

    public static DiveLogData getInstance(Context context) {
        // Log.v(TAG, "getInstance(Context context)");
        if (sInstance == null) {
            sInstance = new DiveLogData(context.getApplicationContext());
        }
        return sInstance;
    }

    public long addDiver(String username, String firstname, String lastname, Long birthdate, Long certificationId) {
        // Log.v(TAG, "addDiver(username = " + username + ", firstname = " + firstname + ", lastname = " + lastname + ", birthdate = " + birthdate + ", certificationId = " + certificationId + ")");
        Uri uri = Uri.withAppendedPath(DiveLogProvider.CONTENT_URI, DiveLogProvider.PATH_DIVERS);
        ContentValues values = new ContentValues();
        values.put(DiveLogDatabaseContract.Divers.COLUMN_NAME_USERNAME, username);
        values.put(DiveLogDatabaseContract.Divers.COLUMN_NAME_FIRSTNAME, firstname);
        values.put(DiveLogDatabaseContract.Divers.COLUMN_NAME_LASTNAME, lastname);
        values.put(DiveLogDatabaseContract.Divers.COLUMN_NAME_BIRTHDATE, birthdate);
        values.put(DiveLogDatabaseContract.Divers.COLUMN_NAME_CERTIFICATION_ID, certificationId);
        Uri newUri = mResolver.insert(
                uri,
                values
        );
        mDiversCount = getRealDiversCount();
        try {
            return Long.valueOf(newUri.getLastPathSegment());
        } catch (NumberFormatException e) {
            Log.e(TAG, "Could not get id of new diver:" + e.getMessage());
            return -1;
        }
    }

    public long addDive(Long startTime, Integer duration, Long siteId, Long diverId,
                        Integer surfaceInterval, Double maxDepth, Double avgDepth, Integer airTemp,
                        Integer surfaceTemp, Integer bottomTemp, Integer tankVolume,
                        Integer startPressure, Integer endPressure, Double weight,
                        Integer o2Percentage, Long buddyId, Long tripId, String logNotes) {
        // Log.v(TAG, "addDive(startTime = " + startTime + ", duration = " + duration + ", siteId = " + siteId + ", diverId = " + diverId + ", surfaceInterval = " + surfaceInterval + ", maxDepth = " + maxDepth + ", avgDepth = " + avgDepth + ", airTemp = " + airTemp + ", surfaceTemp = " + surfaceTemp + ", bottomTemp = " + bottomTemp + ", tankVolume = " + tankVolume + ", startPressure = " + startPressure + ", endPressure = " + endPressure + ", weight = " + weight + ", o2Percentage = " + o2Percentage + ", buddyId = " + buddyId + ", tripId = " + tripId + ", logNotes = " + ((logNotes == null) ? "null" : logNotes.substring(0, 10)) + ")");
        Uri uri = Uri.withAppendedPath(DiveLogProvider.CONTENT_URI, DiveLogProvider.PATH_DIVES);
        ContentValues values = new ContentValues();
        values.put(DiveLogDatabaseContract.Dives.COLUMN_NAME_STARTTIME, startTime);
        values.put(DiveLogDatabaseContract.Dives.COLUMN_NAME_DURATION, duration);
        values.put(DiveLogDatabaseContract.Dives.COLUMN_NAME_SITE_ID, siteId);
        values.put(DiveLogDatabaseContract.Dives.COLUMN_NAME_DIVER_ID, diverId);
        values.put(DiveLogDatabaseContract.Dives.COLUMN_NAME_SURFACEINTERVAL, surfaceInterval);
        values.put(DiveLogDatabaseContract.Dives.COLUMN_NAME_MAXDEPTH, maxDepth);
        values.put(DiveLogDatabaseContract.Dives.COLUMN_NAME_AVGDEPTH, avgDepth);
        values.put(DiveLogDatabaseContract.Dives.COLUMN_NAME_AIRTEMP, airTemp);
        values.put(DiveLogDatabaseContract.Dives.COLUMN_NAME_SURFACETEMP, surfaceTemp);
        values.put(DiveLogDatabaseContract.Dives.COLUMN_NAME_BOTTOMTEMP, bottomTemp);
        values.put(DiveLogDatabaseContract.Dives.COLUMN_NAME_TANKVOLUME, tankVolume);
        values.put(DiveLogDatabaseContract.Dives.COLUMN_NAME_STARTPRESSURE, startPressure);
        values.put(DiveLogDatabaseContract.Dives.COLUMN_NAME_ENDPRESSURE, endPressure);
        values.put(DiveLogDatabaseContract.Dives.COLUMN_NAME_WEIGHT, weight);
        values.put(DiveLogDatabaseContract.Dives.COLUMN_NAME_O2PERCENTAGE, o2Percentage);
        values.put(DiveLogDatabaseContract.Dives.COLUMN_NAME_BUDDY_ID, buddyId);
        values.put(DiveLogDatabaseContract.Dives.COLUMN_NAME_TRIP_ID, tripId);
        values.put(DiveLogDatabaseContract.Dives.COLUMN_NAME_LOGNOTES, logNotes);
        Uri newUri = mResolver.insert(
                uri,
                values
        );
        try {
            return Long.valueOf(newUri.getLastPathSegment());
        } catch (NumberFormatException e) {
            Log.e(TAG, "Could not get id of new dive:" + e.getMessage());
            return -1;
        }
    }
    
    public long addDiveSample(long diveId, int sampleTime, double depth, int pressure, int temperature, DiveSample.Bookmark bookmark, String bookmarkText, double sacRate, int cylinderPressure) {
        // Log.v(TAG, "addDiveSample(diveId = " + diveId + ", sampleTime = " + sampleTime + ", depth = " + depth + ", pressure = " + pressure + ", temperature = " + temperature + ", bookmark = " + bookmark + ", bookmarkText = " + bookmarkText + ", sacRate = " + sacRate + ", cylinderPressure = " + cylinderPressure + ")");
        Uri uri = Uri.withAppendedPath(DiveLogProvider.CONTENT_URI, DiveLogProvider.PATH_SAMPLES);
        ContentValues values = new ContentValues();
        values.put(DiveLogDatabaseContract.DiveSamples.COLUMN_NAME_DIVE_ID, diveId);
        values.put(DiveLogDatabaseContract.DiveSamples.COLUMN_NAME_SAMPLETIME, sampleTime);
        values.put(DiveLogDatabaseContract.DiveSamples.COLUMN_NAME_DEPTH, depth);
        values.put(DiveLogDatabaseContract.DiveSamples.COLUMN_NAME_PRESSURE, pressure);
        values.put(DiveLogDatabaseContract.DiveSamples.COLUMN_NAME_TEMPERATURE, temperature);
        values.put(DiveLogDatabaseContract.DiveSamples.COLUMN_NAME_BOOKMARK, bookmark.getValue());
        if (bookmarkText != null && !bookmarkText.isEmpty()) {
            values.put(DiveLogDatabaseContract.DiveSamples.COLUMN_NAME_BOOKMARKTEXT, bookmarkText);
        }
        values.put(DiveLogDatabaseContract.DiveSamples.COLUMN_NAME_SACRATE, sacRate);
        values.put(DiveLogDatabaseContract.DiveSamples.COLUMN_NAME_CYLINDERPRESSURE, cylinderPressure);
        Uri newUri = mResolver.insert(
                uri,
                values
        );
        try {
            return Long.valueOf(newUri.getLastPathSegment());
        } catch (NumberFormatException e) {
            Log.e(TAG, "Could not get id of new sample:" + e.getMessage());
            return -1;
        }
    }

    public long addDiveOrganization(String name, String fullName) {
        // Log.v(TAG, "addDiveOrganization(name = " + name + ", fullname = " + fullName + ")");
        Uri uri = Uri.withAppendedPath(DiveLogProvider.CONTENT_URI, DiveLogProvider.PATH_ORGANIZATIONS);
        ContentValues values = new ContentValues();
        values.put(DiveLogDatabaseContract.DiveOrganizations.COLUMN_NAME_NAME, name);
        values.put(DiveLogDatabaseContract.DiveOrganizations.COLUMN_NAME_FULLNAME, fullName);
        Uri newUri = mResolver.insert(
                uri,
                values
        );
        try {
            return Long.valueOf(newUri.getLastPathSegment());
        } catch (NumberFormatException e) {
            Log.e(TAG, "Could not get id of new organization:" + e.getMessage());
            return -1;
        }
    }

    public long addDiveCourse(String name, Long organizationId) {
        // Log.v(TAG, "addDiveCourse(name = " + name + ", organizationId = " + organizationId + ")");
        Uri uri = Uri.withAppendedPath(DiveLogProvider.CONTENT_URI, DiveLogProvider.PATH_COURSES);
        ContentValues values = new ContentValues();
        values.put(DiveLogDatabaseContract.DiveCourses.COLUMN_NAME_NAME, name);
        values.put(DiveLogDatabaseContract.DiveCourses.COLUMN_NAME_ORGANIZATION_ID, organizationId);
        Uri newUri = mResolver.insert(
                uri,
                values
        );
        try {
            return Long.valueOf(newUri.getLastPathSegment());
        } catch (NumberFormatException e) {
            Log.e(TAG, "Could not get id of new course:" + e.getMessage());
            return -1;
        }
    }

    public long addDiveCertification(Long diverId, Long date, Long courseId, Long centerId, String number) {
        // Log.v(TAG, "addDiveCertification(diverId = " + diverId + ", date = " + date + ", courseId = " + courseId + ", centerId = " + centerId + ", number = " + number + ")");
        Uri uri = Uri.withAppendedPath(DiveLogProvider.CONTENT_URI, DiveLogProvider.PATH_CERTS);
        ContentValues values = new ContentValues();
        values.put(DiveLogDatabaseContract.DiveCertifications.COLUMN_NAME_DATE, date);
        values.put(DiveLogDatabaseContract.DiveCertifications.COLUMN_NAME_DIVER_ID, diverId);
        values.put(DiveLogDatabaseContract.DiveCertifications.COLUMN_NAME_COURSE_ID, courseId);
        values.put(DiveLogDatabaseContract.DiveCertifications.COLUMN_NAME_CENTER_ID, centerId);
        values.put(DiveLogDatabaseContract.DiveCertifications.COLUMN_NAME_NUMBER, number);
        Uri newUri = mResolver.insert(
                uri,
                values
        );
        try {
            return Long.valueOf(newUri.getLastPathSegment());
        } catch (NumberFormatException e) {
            Log.e(TAG, "Could not get id of new certification:" + e.getMessage());
            return -1;
        }
    }

    public long addDiveCenter(String name, Long locationId, String website) {
        // Log.v(TAG, "addDiveCenter(name = " + name + ", locationId = " + locationId + ", website = " + website + ")");
        Uri uri = Uri.withAppendedPath(DiveLogProvider.CONTENT_URI, DiveLogProvider.PATH_CENTERS);
        ContentValues values = new ContentValues();
        values.put(DiveLogDatabaseContract.DiveCenters.COLUMN_NAME_NAME, name);
        values.put(DiveLogDatabaseContract.DiveCenters.COLUMN_NAME_LOCATION_ID, locationId);
        values.put(DiveLogDatabaseContract.DiveCenters.COLUMN_NAME_WEBSITE, website);
        Uri newUri = mResolver.insert(
                uri,
                values
        );
        try {
            return Long.valueOf(newUri.getLastPathSegment());
        } catch (NumberFormatException e) {
            Log.e(TAG, "Could not get id of new center:" + e.getMessage());
            return -1;
        }
    }

    public long addDiveLocation(String name, Long countryId, Double latitude, Double longitude) {
        // Log.v(TAG, "addDiveLocation(name = " + name + ", countryId = " + countryId + ", latitude = " + latitude + ", longitude = " + longitude + ")");
        Uri uri = Uri.withAppendedPath(DiveLogProvider.CONTENT_URI, DiveLogProvider.PATH_LOCATIONS);
        ContentValues values = new ContentValues();
        values.put(DiveLogDatabaseContract.DiveLocations.COLUMN_NAME_NAME, name);
        values.put(DiveLogDatabaseContract.DiveLocations.COLUMN_NAME_COUNTRY_ID, countryId);
        values.put(DiveLogDatabaseContract.DiveLocations.COLUMN_NAME_LATITUDE, latitude);
        values.put(DiveLogDatabaseContract.DiveLocations.COLUMN_NAME_LONGITUDE, longitude);
        Uri newUri = mResolver.insert(
                uri,
                values
        );
        try {
            return Long.valueOf(newUri.getLastPathSegment());
        } catch (NumberFormatException e) {
            Log.e(TAG, "Could not get id of new location:" + e.getMessage());
            return -1;
        }
    }

    public long addDiveCountry(String name) {
        // Log.v(TAG, "addDiveCountry(name = " + name + ")");
        Uri uri = Uri.withAppendedPath(DiveLogProvider.CONTENT_URI, DiveLogProvider.PATH_COUNTRIES);
        ContentValues values = new ContentValues();
        values.put(DiveLogDatabaseContract.DiveCountries.COLUMN_NAME_NAME, name);
        Uri newUri = mResolver.insert(
                uri,
                values
        );
        try {
            return Long.valueOf(newUri.getLastPathSegment());
        } catch (NumberFormatException e) {
            Log.e(TAG, "Could not get id of new country:" + e.getMessage());
            return -1;
        }
    }

    public long addDiveTrip(String destination) {
        // Log.v(TAG, "addDiveCountry(destination = " + destination + ")");
        Uri uri = Uri.withAppendedPath(DiveLogProvider.CONTENT_URI, DiveLogProvider.PATH_TRIPS);
        ContentValues values = new ContentValues();
        values.put(DiveLogDatabaseContract.DiveTrips.COLUMN_NAME_DESTINATION, destination);
        Uri newUri = mResolver.insert(
                uri,
                values
        );
        try {
            return Long.valueOf(newUri.getLastPathSegment());
        } catch (NumberFormatException e) {
            Log.e(TAG, "Could not get id of new trip:" + e.getMessage());
            return -1;
        }
    }

    public long addDiveSite(String name, Long location_id) {
        // Log.v(TAG, "addDiveSite(name = " + name + ", location_id = " + location_id + ")");
        Uri uri = Uri.withAppendedPath(DiveLogProvider.CONTENT_URI, DiveLogProvider.PATH_SITES);
        ContentValues values = new ContentValues();
        values.put(DiveLogDatabaseContract.DiveSites.COLUMN_NAME_NAME, name);
        values.put(DiveLogDatabaseContract.DiveSites.COLUMN_NAME_LOCATION_ID, location_id);
        Uri newUri = mResolver.insert(
                uri,
                values
        );
        try {
            return Long.valueOf(newUri.getLastPathSegment());
        } catch (NumberFormatException e) {
            Log.e(TAG, "Could not get id of new site:" + e.getMessage());
            return -1;
        }
    }

    public long addDiveBuddy(String name, Long diverId) {
        // Log.v(TAG, "addDiveBuddy(name = " + name + ", diverId = " + diverId + ")");
        Uri uri = Uri.withAppendedPath(DiveLogProvider.CONTENT_URI, DiveLogProvider.PATH_BUDDIES);
        ContentValues values = new ContentValues();
        values.put(DiveLogDatabaseContract.DiveBuddies.COLUMN_NAME_NAME, name);
        values.put(DiveLogDatabaseContract.DiveBuddies.COLUMN_NAME_DIVER_ID, diverId);
        Uri newUri = mResolver.insert(
                uri,
                values
        );
        try {
            return Long.valueOf(newUri.getLastPathSegment());
        } catch (NumberFormatException e) {
            Log.e(TAG, "Could not get id of new buddy:" + e.getMessage());
            return -1;
        }
    }

    public Diver getDiver(long id) {
        // Log.v(TAG, "getDiver(id = " + id + ")");
        Uri uri = Uri.withAppendedPath(DiveLogProvider.CONTENT_URI, DiveLogProvider.PATH_DIVERS + "/" + id);
        String[] projection = DiveLogDatabaseContract.Divers.AllColumns;
        Cursor cursor = mResolver.query(
                uri,
                projection,
                null, // selection
                null, // selectionArgs
                null); // sortOrder
        if (cursor.moveToFirst()) {
            Diver diver = getDiver(cursor);
            cursor.close();
            return diver;
        } else {
            cursor.close();
            throw new Error("Could not find Diver with id = " + id);
        }
    }

    private Diver getDiver(Cursor cursor) {
        Long id = cursor.getLong(cursor.getColumnIndex(DiveLogDatabaseContract.Divers._ID));
        String username = cursor.getString(cursor.getColumnIndex(DiveLogDatabaseContract.Divers.COLUMN_NAME_USERNAME));
        String firstName = cursor.getString(cursor.getColumnIndex(DiveLogDatabaseContract.Divers.COLUMN_NAME_FIRSTNAME));
        String lastName = cursor.getString(cursor.getColumnIndex(DiveLogDatabaseContract.Divers.COLUMN_NAME_LASTNAME));
        Long birthDate = cursor.getLong(cursor.getColumnIndex(DiveLogDatabaseContract.Divers.COLUMN_NAME_BIRTHDATE));
        DiveCertification certification = null;
        if (!cursor.isNull(cursor.getColumnIndex(DiveLogDatabaseContract.Divers.COLUMN_NAME_CERTIFICATION_ID))) {
            Long certificationId = cursor.getLong(cursor.getColumnIndex(DiveLogDatabaseContract.Divers.COLUMN_NAME_CERTIFICATION_ID));
            certification = getDiveCertification(certificationId);
        }
        Diver diver = new Diver(id, username, firstName, lastName, birthDate, certification);
        // Log.v(TAG, "return " + diver);
        return diver;
    }

    public Dive getDive(long id) {
        // Log.v(TAG, "getDive(id = " + id + ")");
        Uri uri = Uri.withAppendedPath(DiveLogProvider.CONTENT_URI, DiveLogProvider.PATH_DIVES + "/" + id);
        String[] projection = DiveLogDatabaseContract.Dives.AllColumns;
        Cursor cursor = mResolver.query(
                uri,
                projection,
                null, // selection
                null, // selectionArgs
                null); // sortOrder
        if (cursor.moveToFirst()) {
            Dive dive = getDive(cursor);
            cursor.close();
            return dive;
        } else {
            throw new Error("Could not find Dive with id = " + id);
        }
    }

    private Dive getDive(Cursor cursor) {
        Long id = cursor.getLong(cursor.getColumnIndex(DiveLogDatabaseContract.Dives._ID));
        Long startTime = cursor.getLong(cursor.getColumnIndex(DiveLogDatabaseContract.Dives.COLUMN_NAME_STARTTIME));
        Integer duration = cursor.getInt(cursor.getColumnIndex(DiveLogDatabaseContract.Dives.COLUMN_NAME_DURATION));
        Integer surfaceInterval = cursor.getInt(cursor.getColumnIndex(DiveLogDatabaseContract.Dives.COLUMN_NAME_SURFACEINTERVAL));
        Double maxDepth = cursor.getDouble(cursor.getColumnIndex(DiveLogDatabaseContract.Dives.COLUMN_NAME_MAXDEPTH));
        Double avgDepth = cursor.getDouble(cursor.getColumnIndex(DiveLogDatabaseContract.Dives.COLUMN_NAME_AVGDEPTH));
        Integer airTemp = cursor.getInt(cursor.getColumnIndex(DiveLogDatabaseContract.Dives.COLUMN_NAME_AIRTEMP));
        Integer surfaceTemp = cursor.getInt(cursor.getColumnIndex(DiveLogDatabaseContract.Dives.COLUMN_NAME_SURFACETEMP));
        Integer bottomTemp = cursor.getInt(cursor.getColumnIndex(DiveLogDatabaseContract.Dives.COLUMN_NAME_BOTTOMTEMP));
        Integer tankVolume = cursor.getInt(cursor.getColumnIndex(DiveLogDatabaseContract.Dives.COLUMN_NAME_TANKVOLUME));
        Integer startPressure = cursor.getInt(cursor.getColumnIndex(DiveLogDatabaseContract.Dives.COLUMN_NAME_STARTPRESSURE));
        Integer endPressure = cursor.getInt(cursor.getColumnIndex(DiveLogDatabaseContract.Dives.COLUMN_NAME_ENDPRESSURE));
        Double weight = cursor.getDouble(cursor.getColumnIndex(DiveLogDatabaseContract.Dives.COLUMN_NAME_WEIGHT));
        Integer o2Percentage = cursor.getInt(cursor.getColumnIndex(DiveLogDatabaseContract.Dives.COLUMN_NAME_O2PERCENTAGE));
        String logNotes = cursor.getString(cursor.getColumnIndex(DiveLogDatabaseContract.Dives.COLUMN_NAME_LOGNOTES));
        DiveSite site = null;
        if (!cursor.isNull(cursor.getColumnIndex(DiveLogDatabaseContract.Dives.COLUMN_NAME_SITE_ID))) {
            long siteId = cursor.getLong(cursor.getColumnIndex(DiveLogDatabaseContract.Dives.COLUMN_NAME_SITE_ID));
            site = getDiveSite(siteId);
        }
        Diver diver = null;
        if (!cursor.isNull(cursor.getColumnIndex(DiveLogDatabaseContract.Dives.COLUMN_NAME_DIVER_ID))) {
            long diverId = cursor.getLong(cursor.getColumnIndex(DiveLogDatabaseContract.Dives.COLUMN_NAME_DIVER_ID));
            diver = getDiver(diverId);
        }
        DiveBuddy buddy = null;
        if (!cursor.isNull(cursor.getColumnIndex(DiveLogDatabaseContract.Dives.COLUMN_NAME_BUDDY_ID))) {
            long buddyId = cursor.getLong(cursor.getColumnIndex(DiveLogDatabaseContract.Dives.COLUMN_NAME_BUDDY_ID));
            buddy = getDiveBuddy(buddyId);
        }
        DiveTrip trip = null;
        if (!cursor.isNull(cursor.getColumnIndex(DiveLogDatabaseContract.Dives.COLUMN_NAME_TRIP_ID))) {
            long tripId = cursor.getLong(cursor.getColumnIndex(DiveLogDatabaseContract.Dives.COLUMN_NAME_TRIP_ID));
            trip = getDiveTrip(tripId);
        }
        Dive dive = new Dive(id, startTime, duration, site, diver, surfaceInterval, maxDepth,
                avgDepth, airTemp, surfaceTemp, bottomTemp, tankVolume, startPressure,
                endPressure, weight, o2Percentage, buddy, trip, logNotes);
        // Log.v(TAG, "return " + dive);
        return dive;
    }
    
    public DiveSample getDiveSample(long id) {
        // Log.v(TAG, "getDiveSample(id = " + id + ")");
        Uri uri = Uri.withAppendedPath(DiveLogProvider.CONTENT_URI, DiveLogProvider.PATH_SAMPLES + "/" + id);
        String[] projection = DiveLogDatabaseContract.DiveSamples.AllColumns;
        Cursor cursor = mResolver.query(
                uri,
                projection,
                null, // selection
                null, // selectionArgs
                null); // sortOrder
        if (cursor.moveToFirst()) {
            long diveId = cursor.getLong(cursor.getColumnIndex(DiveLogDatabaseContract.DiveSamples.COLUMN_NAME_DIVE_ID));
            int sampleTime = cursor.getInt(cursor.getColumnIndex(DiveLogDatabaseContract.DiveSamples.COLUMN_NAME_SAMPLETIME));
            double depth = cursor.getDouble(cursor.getColumnIndex(DiveLogDatabaseContract.DiveSamples.COLUMN_NAME_DEPTH));
            int pressure = cursor.getInt(cursor.getColumnIndex(DiveLogDatabaseContract.DiveSamples.COLUMN_NAME_PRESSURE));
            int temperature = cursor.getInt(cursor.getColumnIndex(DiveLogDatabaseContract.DiveSamples.COLUMN_NAME_TEMPERATURE));
            int bookmarkValue = cursor.getInt(cursor.getColumnIndex(DiveLogDatabaseContract.DiveSamples.COLUMN_NAME_BOOKMARK));
            String bookmarkText = cursor.getString(cursor.getColumnIndex(DiveLogDatabaseContract.DiveSamples.COLUMN_NAME_BOOKMARKTEXT));
            double sacRate = cursor.getDouble(cursor.getColumnIndex(DiveLogDatabaseContract.DiveSamples.COLUMN_NAME_SACRATE));
            int cylinderPressure = cursor.getInt(cursor.getColumnIndex(DiveLogDatabaseContract.DiveSamples.COLUMN_NAME_CYLINDERPRESSURE));
            DiveSample.Bookmark bookmark = DiveSample.Bookmark.fromInt(bookmarkValue);
            DiveSample sample = new DiveSample(id, diveId, sampleTime, depth, pressure, temperature, bookmark, bookmarkText, sacRate, cylinderPressure);
            // Log.v(TAG, "return " + sample);
            cursor.close();
            return sample;
        } else {
            cursor.close();
            throw new Error("Could not find DiveSample with id = " + id);
        }
    }

    public DiveCenter getDiveCenter(long id) {
        // Log.v(TAG, "getDiveCenter(id = " + id + ")");
        Uri uri = Uri.withAppendedPath(DiveLogProvider.CONTENT_URI, DiveLogProvider.PATH_CENTERS + "/" + id);
        String[] projection = DiveLogDatabaseContract.DiveCenters.AllColumns;
        Cursor cursor = mResolver.query(
                uri,
                projection,
                null, // selection
                null, // selectionArgs
                null); // sortOrder
        if (cursor.moveToFirst()) {
            String name = cursor.getString(cursor.getColumnIndex(DiveLogDatabaseContract.DiveCenters.COLUMN_NAME_NAME));
            String website = cursor.getString(cursor.getColumnIndex(DiveLogDatabaseContract.DiveCenters.COLUMN_NAME_WEBSITE));
            DiveLocation location = null;
            if (!cursor.isNull(cursor.getColumnIndex(DiveLogDatabaseContract.DiveCenters.COLUMN_NAME_LOCATION_ID))) {
                long locationId = cursor.getLong(cursor.getColumnIndex(DiveLogDatabaseContract.DiveCenters.COLUMN_NAME_LOCATION_ID));
                location = getDiveLocation(locationId);
            }
            DiveCenter center = new DiveCenter(id, name, location, website);
            // Log.v(TAG, "return " + center);
            cursor.close();
            return center;
        } else {
            throw new Error("Could not find DiveCenter with id = " + id);
        }
    }

    public DiveLocation getDiveLocation(long id) {
        // Log.v(TAG, "getDiveLocation(id = " + id + ")");
        Uri uri = Uri.withAppendedPath(DiveLogProvider.CONTENT_URI, DiveLogProvider.PATH_LOCATIONS + "/" + id);
        String[] projection = DiveLogDatabaseContract.DiveLocations.AllColumns;
        Cursor cursor = mResolver.query(
                uri,
                projection,
                null, // selection
                null, // selectionArgs
                null); // sortOrder
        if (cursor.moveToFirst()) {
            DiveLocation location = getDiveLocation(cursor);
            cursor.close();
            return location;
        } else {
            throw new Error("Could not find DiveLocation with id = " + id);
        }
    }

    private DiveLocation getDiveLocation(Cursor cursor) {
        Long id = cursor.getLong(cursor.getColumnIndex(DiveLogDatabaseContract.DiveLocations._ID));
        String name = cursor.getString(cursor.getColumnIndex(DiveLogDatabaseContract.DiveLocations.COLUMN_NAME_NAME));
        Double latitude = cursor.getDouble(cursor.getColumnIndex(DiveLogDatabaseContract.DiveLocations.COLUMN_NAME_LATITUDE));
        Double longitude = cursor.getDouble(cursor.getColumnIndex(DiveLogDatabaseContract.DiveLocations.COLUMN_NAME_LONGITUDE));
        DiveCountry country = null;
        if (!cursor.isNull(cursor.getColumnIndex(DiveLogDatabaseContract.DiveLocations.COLUMN_NAME_COUNTRY_ID))) {
            long countryId = cursor.getLong(cursor.getColumnIndex(DiveLogDatabaseContract.DiveLocations.COLUMN_NAME_COUNTRY_ID));
            country = getDiveCountry(countryId);
        }
        DiveLocation location = new DiveLocation(id, name, country, latitude, longitude);
        // Log.v(TAG, "return " + location);
        return location;
    }

    public DiveCountry getDiveCountry(long id) {
        // Log.v(TAG, "getDiveCountry(id = " + id + ")");
        Uri uri = Uri.withAppendedPath(DiveLogProvider.CONTENT_URI, DiveLogProvider.PATH_COUNTRIES + "/" + id);
        String[] projection = DiveLogDatabaseContract.DiveCountries.AllColumns;
        Cursor cursor = mResolver.query(
                uri,
                projection,
                null, // selection
                null, // selectionArgs
                null); // sortOrder
        if (cursor.moveToFirst()) {
            String name = cursor.getString(cursor.getColumnIndex(DiveLogDatabaseContract.DiveCountries.COLUMN_NAME_NAME));
            DiveCountry country = new DiveCountry(id, name);
            // Log.v(TAG, "return " + country);
            cursor.close();
            return country;
        } else {
            throw new Error("Could not find DiveCountry with id = " + id);
        }
    }

    public DiveTrip getDiveTrip(long id) {
        // Log.v(TAG, "getDiveTrip(id = " + id + ")");
        Uri uri = Uri.withAppendedPath(DiveLogProvider.CONTENT_URI, DiveLogProvider.PATH_TRIPS + "/" + id);
        String[] projection = DiveLogDatabaseContract.DiveTrips.AllColumns;
        Cursor cursor = mResolver.query(
                uri,
                projection,
                null, // selection
                null, // selectionArgs
                null); // sortOrder
        if (cursor.moveToFirst()) {
            String destination = cursor.getString(cursor.getColumnIndex(DiveLogDatabaseContract.DiveTrips.COLUMN_NAME_DESTINATION));
            DiveTrip trip = new DiveTrip(id, destination);
            // Log.v(TAG, "return " + trip);
            cursor.close();
            return trip;
        } else {
            cursor.close();
            throw new Error("Could not find DiveTrip with id = " + id);
        }
    }

    public DiveSite getDiveSite(long id) {
        // Log.v(TAG, "getDiveSite(id = " + id + ")");
        Uri uri = Uri.withAppendedPath(DiveLogProvider.CONTENT_URI, DiveLogProvider.PATH_SITES + "/" + id);
        String[] projection = DiveLogDatabaseContract.DiveSites.AllColumns;
        Cursor cursor = mResolver.query(
                uri,
                projection,
                null, // selection
                null, // selectionArgs
                null); // sortOrder
        if (cursor.moveToFirst()) {
            String name = cursor.getString(cursor.getColumnIndex(DiveLogDatabaseContract.DiveSites.COLUMN_NAME_NAME));
            DiveLocation location = null;
            if (!cursor.isNull(cursor.getColumnIndex(DiveLogDatabaseContract.DiveSites.COLUMN_NAME_LOCATION_ID))) {
                long locationId = cursor.getLong(cursor.getColumnIndex(DiveLogDatabaseContract.DiveSites.COLUMN_NAME_LOCATION_ID));
                location = getDiveLocation(locationId);
            }
            DiveSite site = new DiveSite(id, name, location);
            // Log.v(TAG, "return " + site);
            cursor.close();
            return site;
        } else {
            cursor.close();
            throw new Error("Could not find DiveSite with id = " + id);
        }
    }

    public DiveBuddy getDiveBuddy(long id) {
        // Log.v(TAG, "getDiveBuddy(id = " + id + ")");
        Uri uri = Uri.withAppendedPath(DiveLogProvider.CONTENT_URI, DiveLogProvider.PATH_BUDDIES + "/" + id);
        String[] projection = DiveLogDatabaseContract.DiveBuddies.AllColumns;
        Cursor cursor = mResolver.query(
                uri,
                projection,
                null, // selection
                null, // selectionArgs
                null); // sortOrder
        if (cursor.moveToFirst()) {
            String name = cursor.getString(cursor.getColumnIndex(DiveLogDatabaseContract.DiveBuddies.COLUMN_NAME_NAME));
            Diver diver = null;
            if (!cursor.isNull(cursor.getColumnIndex(DiveLogDatabaseContract.DiveBuddies.COLUMN_NAME_DIVER_ID))) {
                long diverId = cursor.getLong(cursor.getColumnIndex(DiveLogDatabaseContract.DiveBuddies.COLUMN_NAME_DIVER_ID));
                diver = getDiver(diverId);
            }
            DiveBuddy buddy = new DiveBuddy(id, name, diver);
            // Log.v(TAG, "return " + buddy);
            cursor.close();
            return buddy;
        } else {
            throw new Error("Could not find DiveBuddy with id = " + id);
        }
    }

    public DiveCertification getDiveCertification(long id) {
        // Log.v(TAG, "getDiveCertification(id = " + id + ")");
        Uri uri = Uri.withAppendedPath(DiveLogProvider.CONTENT_URI, DiveLogProvider.PATH_CERTS + "/" + id);
        String[] projection = DiveLogDatabaseContract.DiveCertifications.AllColumns;
        Cursor cursor = mResolver.query(
                uri,
                projection,
                null, // selection
                null, // selectionArgs
                null); // sortOrder
        if (cursor.moveToFirst()) {
            // we don't get the diver_id because that would get us in an endless loop
            long date = cursor.getLong(cursor.getColumnIndex(DiveLogDatabaseContract.DiveCertifications.COLUMN_NAME_DATE));
            String number = cursor.getString(cursor.getColumnIndex(DiveLogDatabaseContract.DiveCertifications.COLUMN_NAME_NUMBER));
            long courseId = cursor.getLong(cursor.getColumnIndex(DiveLogDatabaseContract.DiveCertifications.COLUMN_NAME_COURSE_ID));
            long centerId = cursor.getLong(cursor.getColumnIndex(DiveLogDatabaseContract.DiveCertifications.COLUMN_NAME_CENTER_ID));
            DiveCourse course = getDiveCourse(courseId);
            DiveCenter center = getDiveCenter(centerId);
            DiveCertification certification = new DiveCertification(id, date, course, center, number);
            // Log.v(TAG, "return " + certification);
            cursor.close();
            return certification;
        } else {
            throw new Error("Could not find DiveCertification with id = " + id);
        }
    }

    public DiveCourse getDiveCourse(long id) {
        // Log.v(TAG, "getDiveCourse(id = " + id + ")");
        Uri uri = Uri.withAppendedPath(DiveLogProvider.CONTENT_URI, DiveLogProvider.PATH_COURSES + "/" + id);
        String[] projection = DiveLogDatabaseContract.DiveCourses.AllColumns;
        Cursor cursor = mResolver.query(
                uri,
                projection,
                null, // selection
                null, // selectionArgs
                null); // sortOrder
        if (cursor.moveToFirst()) {
            String name = cursor.getString(cursor.getColumnIndex(DiveLogDatabaseContract.DiveCourses.COLUMN_NAME_NAME));
            DiveOrganization organization = null;
            if (!cursor.isNull(cursor.getColumnIndex(DiveLogDatabaseContract.DiveCourses.COLUMN_NAME_ORGANIZATION_ID))) {
                long organizationId = cursor.getLong(cursor.getColumnIndex(DiveLogDatabaseContract.DiveCourses.COLUMN_NAME_ORGANIZATION_ID));
                organization = getDiveOrganization(organizationId);
            }
            DiveCourse course = new DiveCourse(id, name, organization);
            // Log.v(TAG, "return " + course);
            cursor.close();
            return course;
        } else {
            throw new Error("Could not find DiveCourse with id = " + id);
        }
    }

    public DiveOrganization getDiveOrganization(long id) {
        // Log.v(TAG, "getDiveOrganization(id = " + id + ")");
        Uri uri = Uri.withAppendedPath(DiveLogProvider.CONTENT_URI, DiveLogProvider.PATH_ORGANIZATIONS + "/" + id);
        String[] projection = DiveLogDatabaseContract.DiveOrganizations.AllColumns;
        Cursor cursor = mResolver.query(
                uri,
                projection,
                null, // selection
                null, // selectionArgs
                null); // sortOrder
        if (cursor.moveToFirst()) {
            String name = cursor.getString(cursor.getColumnIndex(DiveLogDatabaseContract.DiveOrganizations.COLUMN_NAME_NAME));
            String fullname = cursor.getString(cursor.getColumnIndex(DiveLogDatabaseContract.DiveOrganizations.COLUMN_NAME_FULLNAME));
            DiveOrganization organization = new DiveOrganization(id, name, fullname);
            // Log.v(TAG, "return " + organization);
            cursor.close();
            return organization;
        } else {
            throw new Error("Could not find DiveOrganization with id = " + id);
        }
    }

    public Dive getDiveByPosition(int position) {
        // Log.v(TAG, "getDiveByPosition(position = " + position + ")");
        Uri uri = Uri.withAppendedPath(DiveLogProvider.CONTENT_URI, DiveLogProvider.PATH_DIVES);
        String[] projection = DiveLogDatabaseContract.Dives.AllColumns;
        String sortOrder = DiveLogDatabaseContract.Dives.COLUMN_NAME_STARTTIME;
        Cursor cursor = mResolver.query(
                uri,
                projection,
                null, // selection
                null, // selectionArgs
                sortOrder); // sortOrder
        if (cursor.moveToPosition(position)) {
            Dive dive = getDive(cursor);
            cursor.close();
            return dive;
        } else {
            throw new Error("Dive requested at position " + position + " but only " + cursor.getCount() + "dives available");
        }
    }

    public Dive getDiveByStartTime(long startTime, Diver diver) {
        // Log.v(TAG, "getDiveByStartTime(startTime = " + startTime + ", diver = " + diver + ")");
        Uri uri = Uri.withAppendedPath(DiveLogProvider.CONTENT_URI, DiveLogProvider.PATH_DIVES);
        String[] projection = DiveLogDatabaseContract.Dives.AllColumns;
        String selection =
                DiveLogDatabaseContract.Dives.COLUMN_NAME_STARTTIME + " = ?" +
                " AND " +
                DiveLogDatabaseContract.Dives.COLUMN_NAME_DIVER_ID + " = ?";
        String[] selectionArgs = {
                String.valueOf(startTime),
                String.valueOf(diver.getId())
        };
        Cursor cursor = mResolver.query(
                uri,
                projection,
                selection,
                selectionArgs,
                null); // sortOrder
        if (cursor.moveToFirst()) {
            Dive dive = getDive(cursor);
            cursor.close();
            return dive;
        } else {
            Log.i(TAG, "Could not find Dive for " + diver.getUsername() + " with startTime = " + startTime);
            return null;
        }
    }

    public int getDiverPosition(long diverId) {
        // Log.v(TAG, "getDiverPosition(diverid = " + diverId + ")");
        Uri uri = Uri.withAppendedPath(DiveLogProvider.CONTENT_URI, DiveLogProvider.PATH_DIVERS);
        String[] projection = DiveLogDatabaseContract.Divers.AllColumns;
        String sortOrder = DiveLogDatabaseContract.Divers.COLUMN_NAME_USERNAME;
        Cursor cursor = mResolver.query(
                uri,
                projection,
                null, // selection
                null, // selectionArgs
                sortOrder); // sortOrder
        if (cursor.moveToFirst()) {
            int position = 0;
            do {
                Long id = cursor.getLong(cursor.getColumnIndex(DiveLogDatabaseContract.Divers._ID));
                if (id.equals(diverId)) {
                    // Log.v(TAG, "return " + position);
                    cursor.close();
                    return position;
                }
                position++;
            } while (cursor.moveToNext());
            cursor.close();
            throw new Error("Requested position for diver with diverid = " + diverId + ", but diver not found");
        } else {
            cursor.close();
            throw new Error("Requested position for diver with diverid = " + diverId + ", but no divers in database");
        }
    }

    public Diver getDiverByUsername(String username) {
        // Log.v(TAG, "getDiverByUsername(username = " + username + ")");
        Uri uri = Uri.withAppendedPath(DiveLogProvider.CONTENT_URI, DiveLogProvider.PATH_DIVERS);
        String[] projection = DiveLogDatabaseContract.Divers.AllColumns;
        String selection = DiveLogDatabaseContract.Divers.COLUMN_NAME_USERNAME + " = ?";
        String[] selectionArgs = {username};
        Cursor cursor = mResolver.query(
                uri,
                projection,
                selection,
                selectionArgs,
                null); // sortOrder
        if (cursor.moveToFirst()) {
            Diver diver = getDiver(cursor);
            cursor.close();
            return diver;
        } else {
            cursor.close();
            Log.e(TAG, "Could not find Diver with username = " + username);
            return null;
        }
    }

    public boolean diverExists(String username) {
        // Log.v(TAG, "diverExists(username = " + username + ")");
        Diver diver = getDiverByUsername(username);
        return (diver != null);
    }

    public int getDiversCount() {
        return mDiversCount;
    }

    public Diver getDiverByPosition(int position) {
        // Log.v(TAG, "getDiverByPosition(position = " + position + ")");
        Uri uri = Uri.withAppendedPath(DiveLogProvider.CONTENT_URI, DiveLogProvider.PATH_DIVERS);
        String[] projection = DiveLogDatabaseContract.Divers.AllColumns;
        String sortOrder = DiveLogDatabaseContract.Divers.COLUMN_NAME_USERNAME;
        Cursor cursor = mResolver.query(
                uri,
                projection,
                null, // selection
                null, // selectionArgs
                sortOrder); // sortOrder
        if (cursor.moveToPosition(position)) {
            Diver diver = getDiver(cursor);
            cursor.close();
            return diver;
        } else {
            cursor.close();
            throw new Error("Diver requested at position " + position + " but only " + cursor.getCount() + " divers available");
        }
    }

    private int getRealDiversCount() {
        // Log.v(TAG, "getRealDiversCount()");
        Uri uri = Uri.withAppendedPath(DiveLogProvider.CONTENT_URI, DiveLogProvider.PATH_DIVERS_COUNT);
        Cursor cursor = mResolver.query(
                uri,
                null, // projection
                null, // selection
                null, // selectionArgs
                null); // sortOrder
        if (cursor.moveToFirst()) {
            int count = cursor.getInt(cursor.getColumnIndex(DiveLogDatabaseContract.COLUMN_NAME_COUNT));
            cursor.close();
            return count;
        } else {
            Log.e(TAG, "Could not get real divers count");
            cursor.close();
            return -1;
        }
    }

    public int getDivesCount(long diverId) {
        Uri uri = Uri.withAppendedPath(DiveLogProvider.CONTENT_URI, DiveLogProvider.PATH_DIVES_COUNT);
        String selection = DiveLogDatabaseContract.Dives.COLUMN_NAME_DIVER_ID + " = ?";
        String[] selectionArgs = new String[] { Long.toString(diverId) };
        Cursor cursor = mResolver.query(
                uri,
                null, // projection
                selection,
                selectionArgs,
                null); // sortOrder
        if (cursor.moveToFirst()) {
            int count = cursor.getInt(cursor.getColumnIndex(DiveLogDatabaseContract.COLUMN_NAME_COUNT));
            cursor.close();
            return count;
        } else {
            Log.e(TAG, "Could not get dives count for diver with id = " + diverId);
            cursor.close();
            return -1;
        }
    }
    
    public int getDiveSamplesCount(long diveId) {
        Uri uri = Uri.withAppendedPath(DiveLogProvider.CONTENT_URI, DiveLogProvider.PATH_SAMPLES_COUNT);
        String selection = DiveLogDatabaseContract.DiveSamples.COLUMN_NAME_DIVE_ID + " = ?";
        String[] selectionArgs = new String[] { Long.toString(diveId) };
        Cursor cursor = mResolver.query(
                uri,
                null, // projection
                selection,
                selectionArgs,
                null); // sortOrder
        if (cursor.moveToFirst()) {
            int count = cursor.getInt(cursor.getColumnIndex(DiveLogDatabaseContract.COLUMN_NAME_COUNT));
            cursor.close();
            return count;
        } else {
            Log.e(TAG, "Could not get samples count for dive with id = " + diveId);
            cursor.close();
            return -1;
        }
    }

    public boolean deleteDiver(long id) {
        Uri uri = Uri.withAppendedPath(DiveLogProvider.CONTENT_URI, DiveLogProvider.PATH_DIVERS);
        String selection = DiveLogDatabaseContract.Divers._ID + " = ?";
        String[] selectionArgs = {Long.toString(id)};
        int count = mResolver.delete(
                uri,
                selection,
                selectionArgs);
        mDiversCount = getRealDiversCount();
        return (count == 1);
    }
    
    public boolean updateDiver(long id, String username, String firstName, String lastName, Long birthDate, Long certificationId) {
        // Log.v(TAG, "updateDiver(id = " + id + ", username = " + username + ", firstName = " + firstName + ", lastName = " + lastName + ", birthDate = " + birthDate + ", certificationId = " + certificationId + ")");
        Uri uri = Uri.withAppendedPath(DiveLogProvider.CONTENT_URI, DiveLogProvider.PATH_DIVERS);
        ContentValues values = new ContentValues();
        if (username != null) {
            Log.i(TAG, "Not updating username because it is null");
            values.put(DiveLogDatabaseContract.Divers.COLUMN_NAME_USERNAME, username);
        }
        values.put(DiveLogDatabaseContract.Divers.COLUMN_NAME_FIRSTNAME, firstName);
        values.put(DiveLogDatabaseContract.Divers.COLUMN_NAME_LASTNAME, lastName);
        values.put(DiveLogDatabaseContract.Divers.COLUMN_NAME_BIRTHDATE, birthDate);
        values.put(DiveLogDatabaseContract.Divers.COLUMN_NAME_CERTIFICATION_ID, certificationId);
        String selection = DiveLogDatabaseContract.Divers._ID + " = ?";
        String[] selectionArgs = {Long.toString(id)};
        int count = mResolver.update(
                uri,
                values,
                selection,
                selectionArgs);
        return (count == 1);
    }

    public boolean updateDive(
        long id, 
        Integer duration, 
        Integer surfaceInterval, 
        Integer o2Percentage, 
        Double maxDepth, 
        Double avgDepth, 
        Integer airTemp, 
        Integer bottomTemp, 
        Integer surfaceTemp, 
        Integer tankVolume, 
        Double weight,
        String logNotes) {
        /* Log.v(TAG, "updateDive(id = " + id + 
           ", duration = " + duration + 
           ", surfaceInterval = " + surfaceInterval + 
           ", o2Percentage = " + o2Percentage + 
           ", maxDepth = " + maxDepth + 
           ", avgDepth = " + avgDepth + 
           ", airTemp = " + airTemp + 
           ", bottomTemp = " + bottomTemp + 
           ", surfaceTemp = " + surfaceTemp + 
           ", tankVolume = " + tankVolume + 
           ", weight = " + weight + 
           ", logNotes = " + ((logNotes == null) ? "null" : logNotes.substring(0, 10)) + ")");*/
        Uri uri = Uri.withAppendedPath(DiveLogProvider.CONTENT_URI, DiveLogProvider.PATH_DIVES);
        ContentValues values = new ContentValues();
        if (duration !=  null) {
            Log.i(TAG, "Not updating duration because it is null");
            values.put(DiveLogDatabaseContract.Dives.COLUMN_NAME_DURATION, duration);
        }
        values.put(DiveLogDatabaseContract.Dives.COLUMN_NAME_SURFACEINTERVAL, surfaceInterval);
        values.put(DiveLogDatabaseContract.Dives.COLUMN_NAME_O2PERCENTAGE, o2Percentage);
        values.put(DiveLogDatabaseContract.Dives.COLUMN_NAME_MAXDEPTH, maxDepth);
        values.put(DiveLogDatabaseContract.Dives.COLUMN_NAME_AVGDEPTH, avgDepth);
        values.put(DiveLogDatabaseContract.Dives.COLUMN_NAME_AIRTEMP, airTemp);
        values.put(DiveLogDatabaseContract.Dives.COLUMN_NAME_BOTTOMTEMP, bottomTemp);
        values.put(DiveLogDatabaseContract.Dives.COLUMN_NAME_SURFACETEMP, surfaceTemp);
        values.put(DiveLogDatabaseContract.Dives.COLUMN_NAME_TANKVOLUME, tankVolume);
        values.put(DiveLogDatabaseContract.Dives.COLUMN_NAME_WEIGHT, weight);
        values.put(DiveLogDatabaseContract.Dives.COLUMN_NAME_LOGNOTES, logNotes);
        String selection = DiveLogDatabaseContract.Dives._ID + " = ?";
        String[] selectionArgs = {Long.toString(id)};
        int count = mResolver.update(
                uri,
                values,
                selection,
                selectionArgs);
        return (count == 1);
    }

    /**
     * Function to insert samples for a specific dive. This function does not use the dive stored in
     * the sample itself to determine for what dive the sample is. Instead, it uses a fixed diveId.
     * @param diveId The id of the dive the samples are added to
     * @param samples The list of samples to add
     * @param deleteExisting If true, delete all existing samples for this diveId before adding the
     *                       new ones
     * @return True if the insert was successful, false if something went wrong
     */
    public boolean insertSamplesForDive(long diveId, List<DiveSample> samples, boolean deleteExisting) {
        // Log.v(TAG, "insertSamplesForDive(diveId = " + diveId + ", List<DiveSample> samples, deleteExisting = " + deleteExisting + ")");
        if (deleteExisting) {
            // Log.d(TAG, "Deleting existing samples");
            deleteSamples(diveId);
        }
        Uri uri = Uri.withAppendedPath(DiveLogProvider.CONTENT_URI, DiveLogProvider.PATH_SAMPLES);
        ContentValues[] insertValues = new ContentValues[samples.size()];
        int i = 0;
        for(DiveSample sample : samples) {
            ContentValues sampleValues = new ContentValues();
            sampleValues.put(DiveLogDatabaseContract.DiveSamples.COLUMN_NAME_DIVE_ID, diveId);
            sampleValues.put(DiveLogDatabaseContract.DiveSamples.COLUMN_NAME_SAMPLETIME, sample.getSampleTime());
            sampleValues.put(DiveLogDatabaseContract.DiveSamples.COLUMN_NAME_DEPTH, sample.getDepth());
            sampleValues.put(DiveLogDatabaseContract.DiveSamples.COLUMN_NAME_PRESSURE, sample.getPressure());
            sampleValues.put(DiveLogDatabaseContract.DiveSamples.COLUMN_NAME_TEMPERATURE, sample.getTemperature());
            sampleValues.put(DiveLogDatabaseContract.DiveSamples.COLUMN_NAME_SACRATE, sample.getSacRate());
            sampleValues.put(DiveLogDatabaseContract.DiveSamples.COLUMN_NAME_CYLINDERPRESSURE, sample.getCylinderPressure());
            sampleValues.put(DiveLogDatabaseContract.DiveSamples.COLUMN_NAME_BOOKMARK, sample.getBookmark().getValue());
            if(sample.getBookmark() == DiveSample.Bookmark.PERSONAL) {
                sampleValues.put(DiveLogDatabaseContract.DiveSamples.COLUMN_NAME_BOOKMARKTEXT, sample.getBookmarkText());
            }
            insertValues[i] = sampleValues;
            i++;
        }
        // Log.d(TAG, "Inserting " + samples.size() + " samples");
        int count = mResolver.bulkInsert(uri, insertValues);
        // Log.d(TAG, count + " samples inserted");
        return (count == samples.size());
    }

    public int deleteSamples(long diveId) {
        Uri uri = Uri.withAppendedPath(DiveLogProvider.CONTENT_URI, DiveLogProvider.PATH_SAMPLES);
        String selection = DiveLogDatabaseContract.DiveSamples.COLUMN_NAME_DIVE_ID + " = ?";
        String[] selectionArgs = {Long.toString(diveId)};
        int count = mResolver.delete(
                uri,
                selection,
                selectionArgs);
        // Log.d(TAG, count + " samples deleted");
        // TODO: Perform VACUUM on samples
        return count;
    }

    public int getTotalBottomTime(long diverId) {
        Uri uri = Uri.withAppendedPath(DiveLogProvider.CONTENT_URI, DiveLogProvider.PATH_DIVERS + "/" + diverId + "/totalbottomtime");
        Cursor cursor = mResolver.query(
                uri,
                null, // projection
                null, // selection
                null, // selectionArgs: diverId is passed in URL
                null); // sortOrder
        if (cursor.moveToFirst()) {
            int stat = cursor.getInt(cursor.getColumnIndex(DiveLogDatabaseContract.COLUMN_NAME_STAT));
            cursor.close();
            return stat;
        } else {
            cursor.close();
            throw new Error("Could not get total bottom time for diver with id = " + diverId);
        }
    }

    public Dive getMinimalSi(long diverId) {
        Uri uri = Uri.withAppendedPath(DiveLogProvider.CONTENT_URI, DiveLogProvider.PATH_DIVERS + "/" + diverId + "/minimalsi");
        Cursor cursor = mResolver.query(
                uri,
                null, // projection
                null, // selection
                null, // selectionArgs: diverId is passed in URL
                null); // sortOrder
        if (cursor.moveToFirst()) {
            // int stat = cursor.getInt(cursor.getColumnIndex(DiveLogDatabaseContract.COLUMN_NAME_STAT));
            Dive dive = getDive(cursor);
            cursor.close();
            return dive;
        } else {
            cursor.close();
            throw new Error("Could not get minimal surface interval for diver with id = " + diverId);
        }
    }

    public Dive getDeepestDive(long diverId) {
        Uri uri = Uri.withAppendedPath(DiveLogProvider.CONTENT_URI, DiveLogProvider.PATH_DIVERS + "/" + diverId + "/deepestdive");
        Cursor cursor = mResolver.query(
                uri,
                null, // projection
                null, // selection
                null, // selectionArgs: diverId is passed in URL
                null); // sortOrder
        if (cursor.moveToFirst()) {
            // int stat = cursor.getInt(cursor.getColumnIndex(DiveLogDatabaseContract.COLUMN_NAME_STAT));
            Dive dive = getDive(cursor);
            cursor.close();
            return dive;
        } else {
            cursor.close();
            throw new Error("Could not get deepest dive for diver with id = " + diverId);
        }
    }

    public Dive getShallowestDive(long diverId) {
        Uri uri = Uri.withAppendedPath(DiveLogProvider.CONTENT_URI, DiveLogProvider.PATH_DIVERS + "/" + diverId + "/shallowestdive");
        Cursor cursor = mResolver.query(
                uri,
                null, // projection
                null, // selection
                null, // selectionArgs: diverId is passed in URL
                null); // sortOrder
        if (cursor.moveToFirst()) {
            // int stat = cursor.getInt(cursor.getColumnIndex(DiveLogDatabaseContract.COLUMN_NAME_STAT));
            Dive dive = getDive(cursor);
            cursor.close();
            return dive;
        } else {
            cursor.close();
            throw new Error("Could not get shallowest dive for diver with id = " + diverId);
        }
    }

    public Dive getColdestDive(long diverId) {
        Uri uri = Uri.withAppendedPath(DiveLogProvider.CONTENT_URI, DiveLogProvider.PATH_DIVERS + "/" + diverId + "/coldestdive");
        Cursor cursor = mResolver.query(
                uri,
                null, // projection
                null, // selection
                null, // selectionArgs: diverId is passed in URL
                null); // sortOrder
        if (cursor.moveToFirst()) {
            // int stat = cursor.getInt(cursor.getColumnIndex(DiveLogDatabaseContract.COLUMN_NAME_STAT));
            Dive dive = getDive(cursor);
            cursor.close();
            return dive;
        } else {
            cursor.close();
            throw new Error("Could not get coldest dive for diver with id = " + diverId);
        }
    }

    public Dive getWarmestDive(long diverId) {
        Uri uri = Uri.withAppendedPath(DiveLogProvider.CONTENT_URI, DiveLogProvider.PATH_DIVERS + "/" + diverId + "/warmestdive");
        Cursor cursor = mResolver.query(
                uri,
                null, // projection
                null, // selection
                null, // selectionArgs: diverId is passed in URL
                null); // sortOrder
        if (cursor.moveToFirst()) {
            // int stat = cursor.getInt(cursor.getColumnIndex(DiveLogDatabaseContract.COLUMN_NAME_STAT));
            Dive dive = getDive(cursor);
            cursor.close();
            return dive;
        } else {
            cursor.close();
            throw new Error("Could not get warmest dive for diver with id = " + diverId);
        }
    }

    public List<DiveLocation> getDiverLocations(long diverId) {
        Uri uri = Uri.withAppendedPath(DiveLogProvider.CONTENT_URI, DiveLogProvider.PATH_DIVERS + "/" + diverId + "/locations");
        Cursor cursor = mResolver.query(
                uri,
                null, // projection
                null, // selection
                null, // selectionArgs: diverId is passed in URL
                null); // sortOrder
        List<DiveLocation> locations = new ArrayList<>();
        while (cursor.moveToNext()) {
            DiveLocation location = getDiveLocation(cursor);
            locations.add(location);
        }
        cursor.close();
        return locations;
    }

    public List<String> getDiverLocationCoordinates(long diverId, String coordinateSeparator) {
        Uri uri = Uri.withAppendedPath(DiveLogProvider.CONTENT_URI, DiveLogProvider.PATH_DIVERS + "/" + diverId + "/locations");
        Cursor cursor = mResolver.query(
                uri,
                null, // projection
                null, // selection
                null, // selectionArgs: diverId is passed in URL
                null); // sortOrder
        List<String> coordinates = new ArrayList<>();
        while (cursor.moveToNext()) {
            Double latitude = cursor.getDouble(cursor.getColumnIndex(DiveLogDatabaseContract.DiveLocations.COLUMN_NAME_LATITUDE));
            Double longitude = cursor.getDouble(cursor.getColumnIndex(DiveLogDatabaseContract.DiveLocations.COLUMN_NAME_LONGITUDE));
            coordinates.add(latitude + coordinateSeparator + longitude);
        }
        cursor.close();
        return coordinates;
    }

}